Icon sizes for Android apps

Finding the correct icon sizes for Android apps can be a weird puzzle. Android’s guidelines on iconography mention a lot of useful information but they don’t break down the actual sizes your graphics designer requires.

Here are the sizes in pixels, calculated using Android’s guidelines on iconography.

LDPI MDPI HDPI XHDPI XXHDPI XXXHDPI
Launch Icons 36×36 48×48 72×72 96×96 144×144 192×192
Action Bar (optical square) 18×18 24×24 36×36 48×48 72×72 96×96
Action Bar (full size) 24×24 32×32 48×48 64×64 96×96 128×128
Small / Contextual Icons (optical square) 9×9 12×12 18×18 24×24 36×36 48×48
Small / Contextual Icons (full size) 12×12 16×16 24×24 32×32 48×48 64×64
Notification Icons (optical square) 16×16 22×22 33×33 44×44 66×66 88×88
Notification Icons (full size) 18×18 24×24 36×36 48×48 72×72 96×96

And finally, the size for the launcher icons for Google Play must be 512×512 pixels.

The Android ecosystem is open to many device manufacturers who build devices on a vast variety of sizes and screen resolutions. That is why Android’s way of calculating sizes for icons is based on relative rather than actual sizes.

As explained in the Iconography Guidelines, MDPI is the base for all calculations. LDPI is calculated as a 3/4 of MDPI, HDPI is 1.5 times larger than MDPI, XHDPI is 2 times MDPI, XXHDPI is 3 times MDPI and XXXHDPI is 4 times MDPI.

On some of the above dimensions you may notice a version for “optical square” and “full size”. Icons must have the full size dimension but you should use the size for optical square and use the rest only when necessary.

Android Studio: Add jar as library?

I’ve been struggling with the same thing for many hours, trying to get the Gson jar to work no less. I finally cracked it – here are the steps I took:

  1. Put the Gson jar (in my case, gson-2.2.4.jar) into the libs folder
  2. Right click it and hit ‘Add as library’
  3. Ensure that compile files('libs/gson-2.2.4.jar') is in your build.gradle file
  4. Do a clean build (you can probably do this fine in Android Studio, but to make sure I navigated in a terminal to the root folder of my app and typed gradlew clean. I’m on Mac OS X, the command might be different on your system

After I did the above three, it started working fine. I think the ‘Add as library’ step was the one I’d previously missed, and it didn’t work until I cleaned it either.

[Edit – added the build.gradle step which is also necessary as others have pointed out]

Source: http://stackoverflow.com/

Only allow input number for google chrome android

HTML:

<input type=”text” id=”test” />

JAVASCRIPT

// utility jQuery plugins
$.fn.blockInput = function (options)
{
// find inserted or removed characters
function findDelta(value, prevValue)
{
var delta = ”;

for (var i = 0; i < value.length; i++) {
var str = value.substr(0, i) +
value.substr(i + value.length – prevValue.length);

if (str === prevValue) delta =
value.substr(i, value.length – prevValue.length);
}

return delta;
}

function isValidChar(c)
{
return new RegExp(options.regex).test(c);
}

function isValidString(str)
{
for (var i = 0; i < str.length; i++)
if (!isValidChar(str.substr(i, 1))) return false;

return true;
}

this.filter(‘input,textarea’).on(‘input’, function ()
{
var val = this.value,
lastVal = $(this).data(‘lastVal’);

// get inserted chars
var inserted = findDelta(val, lastVal);
// get removed chars
var removed = findDelta(lastVal, val);
// determine if user pasted content
var pasted = inserted.length > 1 || (!inserted && !removed);

if (pasted)
{
if (!isValidString(val)) this.value = lastVal;
}
else if (!removed)
{
if (!isValidChar(inserted)) this.value = lastVal;
}

// store current value as last value
$(this).data(‘lastVal’, this.value);
}).on(‘focus’, function ()
{
$(this).data(‘lastVal’, this.value);
});

return this;
};

$(‘#test’).blockInput({ regex: ‘[0-9A-Z]’ });

Nguồn: http://jsfiddle.net/zminic/8Lmay/

How to handle empty space in url when downloading image from web?

completeUrl.add(URLEncoder.encode(finalSeperated[i], "UTF-8"));

For every part of the url between “/”

Then I use:

    ArrayList<String> completeUrlFix = new ArrayList<String>();
    StringBuilder newUrl = new StringBuilder();
    for(String string : completeUrl) {
        if(string.contains("+")) {
            String newString = string.replace("+", "%20");
            completeUrlFix.add(newString);
        } else {
            completeUrlFix.add(string);
        }
    }

    for(String string : completeUrlFix) {
        newUrl.append(string);
    }

To build a proper urlString.

The reason this works is because http needs %20. See Trouble Percent-Encoding Spaces in Javacomment by Powerlord

Delete project in android Studio

This is for Android Studio 1.0.2(Windows7). Right click on the project on project bar and delete.

delete from studio

Then remove the project folder from within your user folder under ‘AndroidStudioProject’ using Windows explorer.

Close the studio and relaunch you will presented with welcome screen. Click on deleted project from left side pane then select the option to remove from the list. Done!

remove from list

How to import eclipse library project to android studio project?

If you’re importing a library as source code into a Gradle-based project, then at the moment there’s no super-easy way to do it (sorry, it’s on the to-do list, see https://code.google.com/p/android/issues/detail?id=62122) so you’ll have to author your own build file for the library. Actually, it might be easier to use the New Module wizard to set up the build file and directory structure, then you can trim it down and copy the files over. This set of steps should get you up and running. It seems like a lot of steps but it should hopefully go pretty quick.

  1. From the File menu, choose New Module…
  2. From the wizard that comes up, choose Android Library
  3. From the next page of the wizard, give it the module name HoloCircularProgressBar, and uncheck the options for Create custom launcher icon and Create activity.
  4. Click Finish on the wizard.

It should add the new module to your project, so you’ll end up with something like this:

Project view after adding new empty library

  1. Delete everything inside the src/main folder.
  2. Now copy AndroidManfiest.xml, ic_launcher-web.png, res, and src from the HoloCircularProgressBar source into the src/main folder.
  3. Rename the src folder that you just copied into src/main to java.
  4. The New Module wizard left some things in the build.gradle file in your HoloCircularProgresBar module/directory (make sure you’re editing that one, not the one for your main app module) we don’t need. Remove the dependencies block and the release block.

At this point you should hopefully be able to build successfully. Now if you want to actually use the module:

  1. Go to File > Project Structure… > Modules > Your main module > Dependencies.
  2. Click on the + button to add a dependency, choose Module dependency, and select HoloCircularProgressBar from the list.

Now import statements and usages of the library should work, and you should be good to go.

Source: http://stackoverflow.com/questions/20310164/how-to-import-eclipse-library-project-from-github-to-android-studio-project

Android Simple Custom View

Android Simple Custom View

android-custom-viewAndroid SDK has a large set of standard views such as Button, TextView and ImageView. However, the framework also enables developers to create custom views that meet unique needs for example a pie chart or donut chart. This post is aiming to show you how to create a new simple custom view, how to draw the shape of the view and how to give it a nice look and feel.

Objectives:

  • How to create a new custom view?
  • How to define custom views attributes?
  • How draw on canvas?
  • How to give your view artistic effects?

( 1 ) Create a new Android project

  • Application Name: Simple Custom View
  • Project Name: android-custom-view
  • Package Name: com.hmkcode.views

( 2 ) Create Custom View

First step in creating a custom view is to extend base class “View“. Also, you must override at least one of the three overloaded constructors. Here we will override the 2-parameter constructor where the first parameter is the context and the second is the set of parameters that will be passed when creating the view in layout XML file.

  • /com/hmkcode/views/SimpleView.java
1
2
3
4
5
6
7
public class SimpleView extends View {
    public SimpleView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

( 3 ) Defining Custom View Attributes

When we add a view to the layout file, we usually set some attribute values such as width, height and so on. If your view has special attribute then you can define custom attributes.

Attributes can be in different format such enum, boolean, float, integer, string…etc.

  • Create a new xml file attrs.xml under /res/values
  • We will define two attributes, first shape attribute of type enum and the second is dim of type dimension.
  • /res/values/attrs.xml
1
2
3
4
5
6
7
8
9
<resources>
    <declare-styleable name="FaceView">
        <attr name="shape" format="enum">
            <enum name="circle" value="0"/>
            <enum name="square" value="1"/>
        </attr>
        <attr name="dim" format="dimension"/>
    </declare-styleable>
</resources>

( 4 ) Adding your Custom View to Layout

After extending View class and defining custom attributes (if needed), you can use the custom view in layout XML files just like other standard views. However, if your view has custom attributes, then you need to define a namespace that your attributes belong to. Custom attribute belong to http://schemas.android.com/apk/res/%5Byour package name].

  • Here we will two SimpleView one with shape=”circle” and the other with shape=”square”
  • /res/layout/activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<LinearLayout
     ....
    ....
    android:orientation="vertical"
    >
    <com.hmkcode.views.SimpleView
            android:id="@+id/simpleViewCircle"
            android:layout_width="140dp"
            android:layout_height="150dp"
            customviews:shape="circle"
            customviews:dim="70dp"
            android:layout_gravity="center_horizontal"
         />
    
     <com.hmkcode.views.SimpleView
            android:id="@+id/simpleViewSquare"
            android:layout_width="140dp"
            android:layout_height="140dp"
            customviews:shape="square"
            customviews:dim="140dp"
            android:layout_gravity="center_horizontal"
         />
     <TextView
         android:id="@+id/tv"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal"
         />
</LinearLayout>

( 5 ) Passing Custom Attributes Values to Custom View Class

Now we the custom view class is not yet aware of the custom attributes “shape and dim”. We need to pass them to the class to use them.

  • src/com/hmkcode/views/SimpleView.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SimpleView extends View {
    float dim;
    int shape;
    public SimpleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.SimpleView,
                0, 0
        );
        
        try {
            dim = a.getDimension(R.styleable.SimpleView_dim, 20f);
            shape = a.getInteger(R.styleable.SimpleView_shape, 0);
        } finally {
            a.recycle();
        }
        
        
    }
...
}

( 6 ) Run & Test

Now at this step you can run the application, however nothing will show up on the screen because our new custom view is still blank or has NO “face” yet. Next we will draw some shape on the canvas so we can see it on the screen.

( 7 ) Draw on Custom View Canvas

  • To draw the custom view shape you need to override onDraw(Canvas) method of the custom view class. All the drawing shall be on the canvas object passed in theonDraw(Canvas) parameter.
  • Our simple custom view will draw a circle or a square based on the “shape” parameter.
  • To draw a circle use Canvas.drawCircle() which takes the x & y of the center of the circle and radius of the circle.
  • To draw a square use Canvas.drawRect() which takes x&y of the top-left and bottom-right corners of the rectangle.
  • Paint object defines the look and feel of the shape suhc as color.
  • src/com/hmkcode/views/SimpleView.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.hmkcode.views;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class SimpleView extends View {
    float dim;
    int shape;
    Paint paint;
    
    public static final int CIRCLE = 0;
    public static final int SQUARE = 1;
    public SimpleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        ....
        }
        
        paint = new Paint();
        paint.setColor(0xfffed325); // yellow
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        switch(shape){
            case CIRCLE:
                canvas.drawCircle(dim, dim, dim, paint);
                break;
            case SQUARE:
                canvas.drawRect(0, 0, dim, dim, paint);
                break;
        }
    }
}

( 8 ) Add Click Listener to Custom View

Like other standard views you can add click listener to your custom views. Here we will add a click listener that displays “Circle” when clicking on circle and and “Square” when clicking on square.

  • scr/com/hmkcode/views/MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.hmkcode.views;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
    SimpleView svCircle;
    SimpleView svSquare;
    TextView tv;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        svCircle = (SimpleView) findViewById(R.id.simpleViewCircle);
        svSquare = (SimpleView) findViewById(R.id.simpleViewSquare);
        tv = (TextView) findViewById(R.id.tv);
        
        svCircle.setOnClickListener(this);
        svSquare.setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
    
        switch(view.getId()){
            case R.id.simpleViewCircle:
                tv.setText("Circle");
                break;
            case R.id.simpleViewSquare:
                tv.setText("Square");
                break;
            
        }
        
    }
    
}

( 9 ) Run & Test

Now if you run the application this time you should be able to see a circle and a square.

android-custom-view

Painless threading

Whenever you first start an Android application, a thread called “main” is automatically created. The main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widgets and this includes the drawing events. It is also the thread you interact with Android widgets on. For instance, if you touch the a button on screen, the UI thread dispatches the touch event to the widget which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget to redraw itself.

This single thread model can yield poor performance in Android applications that do not consider the implications. Since everything happens on a single thread performing long operations, like network access or database queries, on this thread will block the whole user interface. No event can be dispatched, including drawing events, while the long operation is underway. From the user’s perspective, the application appears hung. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous “application not responding” (ANR) dialog.

If you want to see how bad this can look, write a simple application with a button that invokes Thread.sleep(2000) in itsOnClickListener. The button will remain in its pressed state for about 2 seconds before going back to its normal state. When this happens, it is very easy for the user to perceive the application as slow.

Now that you know you must avoid lengthy operations on the UI thread, you will probably use extra threads (background orworker threads) to perform these operations, and rightly so. Let’s take the example of a click listener downloading an image over the network and displaying it in an ImageView:

public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      Bitmap b = loadImageFromNetwork();
      mImageView.setImageBitmap(b);
    }
  }).start();
}

At first, this code seems to be a good solution to your problem, as it does not block the UI thread. Unfortunately, it violates the single thread model: the Android UI toolkit is not thread-safe and must always be manipulated on the UI thread. In this piece of code, the ImageView is manipulated on a worker thread, which can cause really weird problems. Tracking down and fixing such bugs can be difficult and time-consuming.

Android offers several ways to access the UI thread from other threads. You may already be familiar with some of them but here is a comprehensive list:

Any of these classes and methods could be used to correct our previous code example:

public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      final Bitmap b = loadImageFromNetwork();
      mImageView.post(new Runnable() {
        public void run() {
          mImageView.setImageBitmap(b);
        }
      });
    }
  }).start();
}

Unfortunately, these classes and methods also tend to make your code more complicated and more difficult to read. It becomes even worse when your implement complex operations that require frequent UI updates. To remedy this problem, Android 1.5 offers a new utility class, called AsyncTask, that simplifies the creation of long-running tasks that need to communicate with the user interface.

AsyncTask is also available for Android 1.0 and 1.1 under the name UserTask. It offers the exact same API and all you have to do is copy its source code in your application.

The goal of AsyncTask is to take care of thread management for you. Our previous example can easily be rewritten withAsyncTask:

public void onClick(View v) {
  new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<string, void,="" bitmap=""> {
     protected Bitmap doInBackground(String... urls) {
         return loadImageFromNetwork(urls[0]);
     }

     protected void onPostExecute(Bitmap result) {
         mImageView.setImageBitmap(result);
     }
 }

As you can see, AsyncTask must be used by subclassing it. It is also very important to remember that an AsyncTaskinstance has to be created on the UI thread and can be executed only once. You can read the AsyncTask documentation for a full understanding on how to use this class, but here is a quick overview of how it works:

In addition to the official documentation, you can read several complex examples in the source code of Shelves (ShelvesActivity.java and AddBookActivity.java) and Photostream (LoginActivity.java, PhotostreamActivity.java andViewPhotoActivity.java). I highly recommend reading the source code of Shelves to see how to persist tasks across configuration changes and how to cancel them properly when the activity is destroyed.

Nguồn: http://android-developers.blogspot.co.uk/2009/05/painless-threading.html 

Regardless of whether or not you use AsyncTask, always remember these two rules about the single thread model: do not block the UI thread and make sure the Android UI toolkit is only accessed on the UI thread. AsyncTask just makes it easier to do both of these things.

If you want to learn more cool techniques, come join us at Google I/O. Members of the Android team will be there to give aseries of in-depth technical sessions and answer all your questions.