Monday, November 28, 2016

Observable Recyclerview

Observable Recyclerview


First of all we need to add below dependencies into gradle

compile 'com.android.support:design:25.0.1'
compile'com.android.support:recyclerview-v7:25.0.1'

Now we have to create adapter_simple_recyclerview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
android:orientation="vertical" 
   android:layout_width="match_parent"    
    android:layout_height="wrap_content">

    <TextView        
     android:id="@+id/tvName"        
     android:layout_width="wrap_content"        
     android:layout_height="wrap_content"        
     android:padding="10dp"/>

</LinearLayout>


Here is 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">

<!--add Appbar layout-->


    <android.support.design.widget.AppBarLayout        
      android:layout_width="match_parent"        
      android:layout_height="wrap_content">


        <android.support.v7.widget.Toolbar            
         android:id="@+id/toolbar"            
         android:layout_width="match_parent"            
         android:layout_height="?attr/actionBarSize"            
         android:background="?attr/colorPrimary"            
         app:layout_scrollFlags="scroll|enterAlways"            
         app:popupTheme="@style/ThemeOverlay.AppCompat.Light"            
         app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

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



    <!--add NestedScrollView-->

    <android.support.v4.widget.NestedScrollView        
     android:layout_width="match_parent"        
     android:layout_height="match_parent"        
     android:fillViewport="true"        
     app:layout_behavior="@string/appbar_scrolling_view_behavior">
        
      <!--Linear layout to add custom layout-->

        <LinearLayout            
         android:layout_width="match_parent"            
         android:layout_height="match_parent"            
         android:orientation="vertical">

          <!--add textview-->
            <TextView                
              android:layout_width="wrap_content"                
              android:layout_height="wrap_content"                
              android:text="This is Heading textview."                
              android:layout_gravity="center"                
              android:textSize="20sp"                
              android:textColor="#666" />

            <!--add Recyclerview-->
            <android.support.v7.widget.RecyclerView                
             android:id="@+id/rvSimple"                
             android:layout_width="match_parent"                
             android:layout_height="wrap_content"                
             android:scrollbars="vertical" />

        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>

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

Add divider.xml 

<shape xmlns:android="http://schemas.android.com/apk/res/android"    
android:shape="rectangle">

    <solid android:color="#cccccc"/>
    
     <size android:width="1dp"        
     android:height="1dp" />

</shape>



Below is DividerItemDecoration class.

public class DividerItemDecoration extends RecyclerView.ItemDecoration  {

    private Drawable mDivider;
    private boolean mShowFirstDivider = false;
    private boolean mShowLastDivider = false;


    public DividerItemDecoration(Context context, AttributeSet attrs) {
        final TypedArray a = context
                .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider});
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
                                 boolean showLastDivider) {
        this(context, attrs);
        mShowFirstDivider = showFirstDivider;
        mShowLastDivider = showLastDivider;
    }

    public DividerItemDecoration(Drawable divider) {
        mDivider = divider;
    }

    public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
                                 boolean showLastDivider) {
        this(divider);
        mShowFirstDivider = showFirstDivider;
        mShowLastDivider = showLastDivider;
    }

    @Override    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
                               RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (mDivider == null) {
            return;
        }
        if (parent.getChildPosition(view) < 1) {
            return;
        }

        if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
            outRect.top = mDivider.getIntrinsicHeight();
        } else {
            outRect.left = mDivider.getIntrinsicWidth();
        }
    }

    @Override    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mDivider == null) {
            super.onDrawOver(c, parent, state);
            return;
        }

        // Initialization needed to avoid compiler warning

        int left = 0, right = 0, top = 0, bottom = 0, size;
        int orientation = getOrientation(parent);
        int childCount = parent.getChildCount();

        if (orientation == LinearLayoutManager.VERTICAL) {
            size = mDivider.getIntrinsicHeight();
            left = parent.getPaddingLeft();
            right = parent.getWidth() - parent.getPaddingRight();
        } else { //horizontal            size = mDivider.getIntrinsicWidth();
            top = parent.getPaddingTop();
            bottom = parent.getHeight() - parent.getPaddingBottom();
        }

        for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            if (orientation == LinearLayoutManager.VERTICAL) {
                top = child.getTop() - params.topMargin;
                bottom = top + size;
            } else { //horizontal                left = child.getLeft() - params.leftMargin;
                right = left + size;
            }
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }

        // show last divider        if (mShowLastDivider && childCount > 0) {
            View child = parent.getChildAt(childCount - 1);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            if (orientation == LinearLayoutManager.VERTICAL) {
                top = child.getBottom() + params.bottomMargin;
                bottom = top + size;
            } else { // horizontal                left = child.getRight() + params.rightMargin;
                right = left + size;
            }
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private int getOrientation(RecyclerView parent) {
        if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
            return layoutManager.getOrientation();
        } else {
            throw new IllegalStateException(
                    "DividerItemDecoration can only be used with a LinearLayoutManager.");
        }
    }

}

Below is studentModel class.

public class StudentModel implements Serializable {

    private String strName;

    public String getStrName() {
        return strName;
    }

    public void setStrName(String strName) {
        this.strName = strName;
    }
}

Here is SimpleRecyclerAdapter.

public class SimpleRecyclerAdapter extends RecyclerView.Adapter<SimpleRecyclerAdapter.SimpleViewHolder> {

    private ArrayList<StudentModel> alStudent;

    public SimpleRecyclerAdapter(ArrayList<StudentModel> alStudent) {

        this.alStudent = alStudent;
        Log.e("Arraylist size ","In Adapter ===> "+alStudent.size());
    }

    @Override    public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_simple_recyclerview, parent, false);
        return new SimpleViewHolder(itemView);
    }

    @Override    public void onBindViewHolder(SimpleViewHolder holder, int position) {
        holder.tvName.setText(alStudent.get(position).getStrName());
    }


    @Override    public int getItemCount() {
        return alStudent.size();
    }

    public class SimpleViewHolder extends RecyclerView.ViewHolder {

        private TextView tvName;

        public SimpleViewHolder(View itemView) {
            super(itemView);

            tvName = (TextView) itemView.findViewById(R.id.tvName);
        }
    }

}


Here is my MainActivity.

public class MainActivity extends AppCompatActivity {

    private ArrayList<StudentModel> alStudent;
    private RecyclerView rvSimple;
    private SimpleRecyclerAdapter simpleRecyclerAdapter;
    private StudentModel model;
    private int s=0;
    private LinearLayoutManager linearLayoutManager;


    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        alStudent = new ArrayList<>();

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);


        getId();
        loadArrayList();
        setRecycler();

    }

    private void setRecycler() {
        try {
            linearLayoutManager = new LinearLayoutManager(MainActivity.this);
            rvSimple.setLayoutManager(linearLayoutManager);

            //add devider to recycleview.

            rvSimple.addItemDecoration(new DividerItemDecoration(getResources().getDrawable(R.drawable.divider)));

            // adapter initialized.

            simpleRecyclerAdapter = new SimpleRecyclerAdapter(alStudent);
            rvSimple.setAdapter(simpleRecyclerAdapter);

            simpleRecyclerAdapter.notifyDataSetChanged();
        } catch (Resources.NotFoundException e) {
            e.printStackTrace();
        }
    }

    private void loadArrayList() {
        try {
            for (int i = 0; i <= 50; i++) {

                model = new StudentModel();
                model.setStrName("Student "+s);
                alStudent.add(model);
                s++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getId() {
        try {
            rvSimple = (RecyclerView)findViewById(R.id.rvSimple);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Thursday, November 24, 2016

Collapsing ToolbarLayout using Design support library (IV)

Collapsing Toolbar layout using Coordinator Layout


In this tutorial, you will learn to hide and show Toolbar/AppBarLayout while scrolling the content/screen like Google play music, play store. If your application/game requires more space then you can hide toolbar on scroll. You can also do same thing for TabLayout also if you are using tabs along.

Before going to start we must be add below dependencies into gradle file.


compile 'com.android.support:design:25.0.1'

compile 'com.android.support:palette-v7:25.0.1' 


First of all we have to define custom style.


style.xml

<resources>

    <!--Make sure in AppTheme use NoActionBar like blow-->    <!-- Base application theme. -->

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->

        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>


    <!--below two stle are used for collaps  toolbar.-->

    <style name="expandedappbar" parent="@android:style/TextAppearance.Medium">
        <item name="android:textSize">48sp</item>
        <item name="android:textColor">@color/white</item>
        <item name="android:textStyle">bold</item>
    </style>

    <style name="collapsedappbar" parent="@android:style/TextAppearance.Medium">
        <item name="android:textSize">18sp</item>
        <item name="android:textColor">@color/white</item>
    </style>

</resources>

Below is color.xml


<?xml version="1.0" encoding="utf-8"?><resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>

    <color name="primary_dark">#303F9F</color>
    <color name="accent">#FF4081</color>
    <color name="white">#ffffff</color>
    <color name="black">#000000</color>

</resources>

Here is string.xml file.



<resources>
    <string name="app_name">Collapsing Toolbar Example</string>
    <string name="user_name">First Name</string>
</resources>


Add code to activity_mail.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:layout_width="match_parent"        
     android:layout_height="250dp"        
     android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
        <android.support.design.widget.CollapsingToolbarLayout            
         android:id="@+id/collapsing_toolbar"            
         android:layout_width="match_parent"            
         android:layout_height="match_parent"            
         app:layout_scrollFlags="scroll|exitUntilCollapsed">
            <!--app:contentScrim="?attr/colorPrimary"-->


            <ImageView                 
             android:layout_width="match_parent"                
             android:layout_height="match_parent"                
             android:scaleType="centerCrop"                
             android:fitsSystemWindows="true"                
             android:background="@drawable/profile_pic"                
             android:id="@+id/profile_id"                
             app:layout_collapseMode="parallax" />

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

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


    <android.support.v4.widget.NestedScrollView        
     android:layout_width="match_parent"        
     android:layout_height="match_parent"        
     app:layout_behavior="@string/appbar_scrolling_view_behavior">

     
   <LinearLayout            
    android:layout_width="match_parent"            
    android:layout_height="match_parent"            
    android:orientation="vertical"            
    android:paddingTop="10dp">


    </LinearLayout>


    </android.support.v4.widget.NestedScrollView>

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

Here is my MainActivity.

public class MainActivity extends AppCompatActivity {

    private CollapsingToolbarLayout collapsingToolbarLayout = null;

    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);

        collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        collapsingToolbarLayout.setTitle(getResources().getString(R.string.user_name));

        dynamicToolbarColor();

        toolbarTextAppernce();
    }


    private void dynamicToolbarColor() {

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.profile_pic);
        Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
            @Override            public void onGenerated(Palette palette) {
                collapsingToolbarLayout.setContentScrimColor(palette.getMutedColor(R.color.colorPrimary));
                collapsingToolbarLayout.setStatusBarScrimColor(palette.getMutedColor(R.color.colorPrimaryDark));
            }
        });
    }


    private void toolbarTextAppernce() {
        collapsingToolbarLayout.setCollapsedTitleTextAppearance(R.style.collapsedappbar);
        collapsingToolbarLayout.setExpandedTitleTextAppearance(R.style.expandedappbar);
    }
}

Tuesday, November 22, 2016

Listview example using BaseAdapter in Android

Listview Exaple

ListView only displays a list of scrollable items and the list items are automatically inserted to the list using an Adapter. 

To make custom android ListView you need to create two XML layout files.One layout for ListView and another layout to hold the raw items of ListView, it contains one ImageView and one TextView inside LinearLayout. You can add more views according to your need.

Below is my activity_main.xml.



<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lvFirst"
/>
</RelativeLayout>



And for custom listview layout we need to create its layout file. Below is my_layout.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</LinearLayout>


Here is my MainActivity.java file.




public class MainActivity extends Activity {

private ArrayList<MyModel> alName;
private ListView lvFirst;
private MyAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

getId();
loadArraylist();
adapter = new MyAdapter(MainActivity.this,alName);
lvFirst.setAdapter(adapter);
adapter.notifyDataSetChanged();

}

private void loadArraylist()
{
alName = new ArrayList<MyModel>();

alName.add(new MyModel("Testing1"));
alName.add(new MyModel("Testing2"));
alName.add(new MyModel("Testing3"));
alName.add(new MyModel("Testing4"));
alName.add(new MyModel("Testing5"));

}

private void getId()
{
lvFirst = (ListView)findViewById(R.id.lvFirst);
}
}

Here is my Model class.




public class MyModel implements Serializable {

private String strName;

public MyModel(String strName)
{
this.strName = strName;
}

public String getStrName()
{
return strName;
}

public void setStrName(String strName)
{
this.strName = strName;
}
}

Here is my listview adapter file

public class MyAdapter extends BaseAdapter {

private Context context;
private ArrayList<MyModel> alName;
private LayoutInflater inflater;

public MyAdapter(MainActivity mainActivity, ArrayList<MyModel> alName)
{
context = mainActivity;
this.alName = alName;
}

@Override
public int getCount()
{
return alName.size();
}

@Override
public Object getItem(int position)
{
return position;
}

@Override
public long getItemId(int position)
{
return position;
}

// View holder is used to avoid findView by id and increase 15 % faster performance.

public class Holder {
TextView tvName;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View myView = null;
try
{
Holder holder;
myView = convertView;

if (myView == null)
{
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myView = inflater.inflate(R.layout.my_layout, null);

//               if pass null in attach to root then app won't be crash and inflate custom layout if we use true
//               then parent view will be use so we can not inflate our custom laoyout.


//                http://stackoverflow.com/questions/21212372/exception-in-adapter-whe  n-trying-to-inflate-layout (for more information.)

holder = new Holder();
holder.tvName = (TextView) myView.findViewById(R.id.tvName);
myView.setTag(holder);

}
else
{
holder = (Holder) myView.getTag();
}

holder.tvName.setText(alName.get(position).getStrName());

} catch (Exception e)
{
e.printStackTrace();
}

return myView;
}
}