Saturday, February 13, 2016

Snackbar and FloatingButton Behavior

Snackbar is just an extension of Toast. It is an actionable Toast. Snackbar will stay on the screen forever or for a short duration (Snackbar.LENGTH_INDEFINITE, SnackBar.LENGTH_LONG, Snackbar.LENGTH_SHORT) and we can set action as well. One example that is coming to my mind is, from a list user deleted an item, then we can give user the option to "Undo" using Snackbar.

Now we will come to the implementation part.

Snackbar snackbar = Snackbar.make(recyclerView, "Do you want to undo", Snackbar.LENGTH_LONG).setAction("Undo", snackBarClickListener);
snackbar.setActionTextColor(Color.WHITE);
View snackbarView = snackbar.getView();
snackbarView.setBackgroundColor(Color.DKGRAY);
snackbar.getView().addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {

     @Override
     public void onViewAttachedToWindow(View v) {
        // write your code here
     }

     @Override
     public void onViewDetachedFromWindow(View v) {
        // write your code here
     }
});
Now about the floating button. Floating button is like when the snackbar appears, floating button floats. We will see the implementation. Here the floating action button is bottom right side. The xml to be defined in the layout is,

<android.support.design.widget.FloatingActionButton
        android:id="@+id/bottom_right_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:src="@drawable/foooooo"
        app:backgroundTint="#some color"
        app:elevation="6dp"
        app:fabSize="normal"
        app:rippleColor="# some color"
        app:layout_behavior="com.smartandroidians.FloatingActionButtonBehavior"
        android:layout_marginBottom="@dimen/fab_margin_bottom"
        android:layout_marginRight="@dimen/fab_margin_right"
        app:layout_anchorGravity="bottom|right|end" />
Now the class of FloatingActionButton is as follows,
public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior {

    public FloatingActionButtonBehavior(Context context, AttributeSet attrs) {
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
        return dependency instanceof Snackbar.SnackbarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
        float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
        child.setTranslationY(translationY);
        return true;
    }
}
This is in the new android design support library. In gradle file, add this line as
dependencies {
  compile 'com.android.support:design:22.2.1'
}
Then if you are using proguard file, then all these lines, otherwise FloatingActionButtonBehavior class won't accept the proguard.
-keepclasseswithmembers class * {
    native ;
}

-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet, int);
}
If you want to know more about proguard settings, please check here

One last point is, for FloatingActionButton should be in CoordinatorLayout. the xml is as,
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/rootLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
That's it !!! Enjoy Coding !!!

DialogFragment - Where to use OnDismissListener and OnCancelListener

If you want to use OnCancelListener or OnDismissListener on dialog fragment, use it in onStart() rather than on onCreateDialog(); 

How to get a Color from hexadecimal Color String

To get the color int from hexadecimal string use the parseColor() methood from android.graphics.Color class

eg: int color = Color.parseColor("#FFFF0000");

Friday, December 11, 2015

keepclasseswithmembernames and keepclasseswithmembers difference

Some of the important attributes in proguard project properties include

-keep attribute
can be used with class, inteface enum etc

eg: -keep class com.smartandroidians.views.FloatingActionButtonBehavior which is not used in any java class and only used in xml files just like a string as

app:layout_behavior="com.smartandroidians.views.FloatingActionButtonBehavior"

proguard remove this class because it feels like it is not used anywhere but it is a very important class  for the app rather floating button to function.

Solution.
1) You can do something like this,
-keep class com.smartandroidians.views.FloatingActionButtonBehavior { *; }

or rather better approach is

2) -keepclasseswithmembernames class * {
    public (android.content.Context, android.util.AttributeSet);
}

How to get the package name of default sms app


Code snippet for getting the default package name of SMS

for below kitkat

String defApp = Settings.Secure.getString(getContentResolver(), "sms_default_application");
PackageManager pm = getApplicationContext().getPackageManager();
Intent iIntent = pm.getLaunchIntentForPackage(defApp);
ResolveInfo mInfo = pm.resolveActivity(iIntent,0);
Log.i(TAG, "apk:"+mInfo.activityInfo.packageName);
above or equal to kitkat

Telephony.Sms.getDefaultSmsPackage(this)


SQLite no concept of boolean - stored as 0 or 1

A simple but useful

SQLite does not have a separate Boolean storage class. Instead, Boolean values are stored as integers 0 (false) and 1 (true).

Eg:
select * from table where deleted='false' which is wrong instead you have to write 
select * from table where deleted=0

Saturday, March 21, 2015

How to use callback or interface - Pass data from Asynctask to activity



To get data from a separate thread to the the main UI thread which will be in different stand alone class can get the result through callbacks. Consider AsyncTask in a separate stand alone class and we need to get data from AsyncTask to the Activity, we can get it through callbacks. The steps are as,

1. Define an interface in AsyncTask
2. Pass the object of interface when calling AsyncTask from Activity
3. In AsyncTask onPostExecute() pass the result to activity

class MyTask extends AsyncTask {
public interface OnUpdateListener {
public void onUpdate(MyObject obj);
}
OnUpdateListener listener;
MyTask() {
}
public void setUpdateListener(OnUpdateListener listener) {
this.listener = listener;
}
MyObject doInBackground() {
return obj;
}
onPostExecute(MyObject obj) {
if (listener != null) {
listener.onUpdate(obj);
}
}

}

In Activity, we can get the object by

MyActivity extends Activity {
void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyTask  task = new MyTask();
task. setUpdateListener(new MyTask. OnUpdateListener() {
public void onUpdate(MyObject obj) {
.....
}
});
task.execute();
}
}

Reference: http://stackoverflow.com/questions/12575068/how-to-get-the-result-of-onpostexecute-to-main-activity-because-asynctask-is-a

Androidians