Working with Material Design and Activity Transition

Screen Shot 2015-09-18 at 1.33.51 am

In the following tutorial we will learn how to use material design and some of it’s components like CoordinatorLayout, Collapsing Toolbar, recyclerview and activity transition.

First of all we will add these dependencies in the build.gradle file in the app folder.

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.android.support:recyclerview-v7:22.2.0'
compile 'com.android.support:design:22.2.0'
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.squareup.picasso:picasso:2.5.2'
}

activity_main.xml

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="192dp"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapseToolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="80dp"
            app:expandedTitleMarginStart="30dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:title="Custom Layout">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                android:scaleType="fitXY"
                android:src="@drawable/bridge"
                app:layout_collapseMode="pin"
                app:layout_collapseParallaxMultiplier="1.5"/>


            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?android:attr/actionBarSize"
                app:layout_collapseMode="pin"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:backgroundTint="@android:color/holo_blue_dark"
        app:elevation="10dp"
        android:translationZ="10dp"
        android:layout_marginRight="20dp"
        app:layout_anchor="@+id/appBar"
        app:layout_anchorGravity="bottom|right|end"
        app:borderWidth="0dp"
        android:visibility="gone"
        android:src="@drawable/plus" />
    <android.support.v7.widget.RecyclerView
        android:id="@+id/uid"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

In the layout you can customize according to the requirements:

In CollapsingToolbarLayout you can change the color of scrim by changing value to this tag:

app:contentScrim="?attr/colorPrimary"

If the value is pin, that means the layout will be pinned when it is scrolled to top. If parallax is used here then the layout will hide when it is scrolled to top.

app:layout_collapseMode="pin"

FloatingActionButton can be positioned wherever required by changing the value inside

app:layout_anchorGravity="bottom|right|end"

The following tag defines that respective to which layout/element the FloatingActionButton will be positioned

app:layout_anchor="@+id/appBar"

In MainActivity we define attributes for toolbar and CollapsingToolbarLayout as follows:

private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;
    Toolbar toolbar;
    FloatingActionButton floatingActionButton;
    CollapsingToolbarLayout collapse;
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar= (Toolbar) findViewById(R.id.toolbar);
        floatingActionButton=(FloatingActionButton) findViewById(R.id.fab);
        collapse=(CollapsingToolbarLayout) findViewById(R.id.collapseToolbar);
       //Setting toolbar as actionbar
        setSupportActionBar(toolbar);
       //Enabling home button
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
       //Setting title of CollapsingToolbarLayout
        collapse.setTitle("Title");
      //Setting color of title when CollapsingToolbarLayout is collapsed
        collapse.setCollapsedTitleTextColor(Color.parseColor("#FFFFFF"));
      //Setting color of title when CollapsingToolbarLayout is expanded
        collapse.setExpandedTitleColor(Color.parseColor("#FFFFFF"));
        collapse.setStatusBarScrimColor(Color.parseColor("#FFFFFF"));
        
        mRecyclerView = (RecyclerView) findViewById(R.id.uid);
        mRecyclerView.setHasFixedSize(true);
        LinearLayoutManager llm = new LinearLayoutManager(this);
        llm.setOrientation(LinearLayoutManager.VERTICAL);

Then we create adapter for recyclerview as follows:

MyAdapter.java

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private ArrayList<String> mDataset;
    private ArrayList<String> ImageArray;
    Context context;

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView mTextView;
        public ImageView mImageView;
        public ViewHolder(View v) {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.person_name);
            mImageView=(ImageView) v.findViewById(R.id.imagess);
        }
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(MainActivity activity,ArrayList<String> myDataset,ArrayList<String> imageArray) {
        context=activity;
        mDataset=new ArrayList<>();
        ImageArray=new ArrayList<>();
        mDataset = myDataset;
        ImageArray=imageArray;

    }

    // Create new views (invoked by the layout manager)
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_layout, parent, false);
        // set the view's size, margins, paddings and layout parameters
        //  ...
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        holder.mTextView.setText(mDataset.get(position));
        Picasso.with(context).load(ImageArray.get(position)).placeholder(R.drawable.photo).into(holder.mImageView);
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }
}

After that we make click listener for the items of recyclerview:

RecyclerItemClickListener.java

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
    private OnItemClickListener mListener;

    public interface OnItemClickListener {
        public void onItemClick(View view, int position);
    }

    GestureDetector mGestureDetector;

    public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
        mListener = listener;
        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
        View childView = view.findChildViewUnder(e.getX(), e.getY());
        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

In MainActivity we use the recyclerview item click as follows:

mAdapter = new MyAdapter(MainActivity.this,myDataset,mImageArray);
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.addOnItemTouchListener(
                new RecyclerItemClickListener(this,new RecyclerItemClickListener.OnItemClickListener(){
                    @Override
                    public void onItemClick(View view,int position){
                        // TODO Handle item click
                        Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
                        intent.putExtra(DetailsActivity.Names,myDataset.get(position));
                        intent.putExtra(DetailsActivity.ImageTs,mImageArray.get(position));
                        //startActivity(intent);
                        ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
                          // the context of the activity
                                MainActivity.this,
                                // For each shared element, add to this method a new Pair item,
                                // which contains the reference of the view we are transitioning *from*,
                                // and the value of the transitionName attribute
                                new Pair<View, String>(view.findViewById(R.id.imagess),
                                        getString(R.string.transition_name_circle)),
                                new Pair<View, String>(view.findViewById(R.id.person_name),
                                        getString(R.string.transition_name_name))
                        );

                        ActivityCompat.startActivity(MainActivity.this, intent, options.toBundle());
                    }
                })
        );

In styles.xml we define how the window enter and exit transition will work:

styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>
    <style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/color_primary</item>
        <item name="colorPrimaryDark">@color/color_primary_dark</item>
        <item name="colorAccent">@color/accent_color</item>
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowContentTransitions">true</item>

        <item name="android:windowEnterTransition">@android:transition/slide_bottom</item>
        <item name="android:windowExitTransition">@android:transition/slide_bottom</item>

        <item name="android:windowAllowEnterTransitionOverlap">true</item>
        <item name="android:windowAllowReturnTransitionOverlap">true</item>
        <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
        <item name="android:windowSharedElementExitTransition">@android:transition/move</item>

        <!-- <item name="android:checkboxStyle">@style/CheckBoxAppTheme</item>
         <item name="android:radioButtonStyle">@style/RadioButtonAppTheme</item>
         <item name="android:datePickerDialogTheme">@style/MyDatePickerStyle</item>-->
    </style>
</resources>

Finally we show the text and image in DetailsActivity

DetailsActivity.java

package materialdemo.androidbeasts.com.materialdesigndemo;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;


public class DetailsActivity extends ActionBarActivity {
    public final static String Names="Name";
    public final static String ImageTs="ImageTs";
    TextView names;
    ImageView images;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_details);
        names=(TextView) findViewById(R.id.big_text);
        images=(ImageView) findViewById(R.id.imageIS);
        names.setText(getIntent().getStringExtra(Names));
        Picasso.with(this).load(getIntent().getStringExtra(ImageTs)).placeholder(R.drawable.photo).into(images);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_details, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

You can download full code here, Please do not forget to subscribe for latest updates:

DOWNLOAD FULL CODE

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s