Showing posts with label RecyclerView. Show all posts
Showing posts with label RecyclerView. Show all posts

Friday, May 20, 2016

SwipeRefreshLayout, work with RecyclerView


Last two post show "Simple example of using SwipeRefreshLayout" and "SwipeRefreshLayout, refresh in background thread", target to ListView.

This example show how SwipeRefreshLayout work with RecyclerView (reference: step-by-step of using RecyclerView).


To use RecyclerView in your Android Studio project, you have to Add Support Libraries of RecyclerView as dependencies.


Create layout/layout_item.xml, to define the layout of RecyclerView item.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/item_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="28dp"/>

</LinearLayout>

Create a new class, RecyclerViewAdapter.java.
package com.blogspot.android_er.androidswiperefresh;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ItemHolder>{

    private List<String> itemsList;
    private OnItemClickListener onItemClickListener;
    private LayoutInflater layoutInflater;

    public RecyclerViewAdapter(Context context){
        layoutInflater = LayoutInflater.from(context);
        itemsList = new ArrayList<String>();
    }

    @Override
    public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = layoutInflater.inflate(R.layout.layout_item, parent, false);
        return new ItemHolder(itemView, this);
    }

    @Override
    public void onBindViewHolder(ItemHolder holder, int position) {
        holder.setItemText(itemsList.get(position));
    }

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

    public void setOnItemClickListener(OnItemClickListener listener){
        onItemClickListener = listener;
    }

    public OnItemClickListener getOnItemClickListener(){
        return onItemClickListener;
    }

    public interface OnItemClickListener{
        public void onItemClick(ItemHolder item, int position);
    }

    public void add(int location, String iString){
        itemsList.add(location, iString);
        notifyItemInserted(location);
    }

    public void set(int location, String iString){
        itemsList.set(location, iString);
        notifyItemChanged(location);
    }

    public void clear(){
        itemsList.clear();
        notifyDataSetChanged();
    }

    public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        private RecyclerViewAdapter parent;
        TextView textItemText;

        public ItemHolder(View itemView, RecyclerViewAdapter parent) {
            super(itemView);
            itemView.setOnClickListener(this);
            this.parent = parent;
            textItemText = (TextView) itemView.findViewById(R.id.item_text);
        }

        public void setItemText(CharSequence itemString){
            textItemText.setText(itemString);
        }

        public CharSequence getItemText(){
            return textItemText.getText();
        }

        @Override
        public void onClick(View v) {
            final OnItemClickListener listener = parent.getOnItemClickListener();
            if(listener != null){
                listener.onItemClick(this, getAdapterPosition());
            }
        }
    }
}


Modify layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:padding="16dp"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidswiperefresh.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/clearall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Clear All"/>

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swiperefreshlayout"
        android:layout_height="match_parent"
        android:layout_width="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/myrecyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

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

</LinearLayout>


MainActivity.java
package com.blogspot.android_er.androidswiperefresh;

import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.text.DateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.OnItemClickListener{

    SwipeRefreshLayout swipeRefreshLayout;
    Button btnClearAll;

    private RecyclerView myRecyclerView;
    private LinearLayoutManager linearLayoutManager;
    private RecyclerViewAdapter myRecyclerViewAdapter;

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

        swipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.swiperefreshlayout);
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refresh();
            }
        });
        btnClearAll = (Button)findViewById(R.id.clearall);
        btnClearAll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //In order to prevent the racing condition of updating removed item in refreshing,
                //disable "Clear All" if refreshing
                if(!swipeRefreshLayout.isRefreshing()){
                    myRecyclerViewAdapter.clear();
                }
            }
        });

        myRecyclerView = (RecyclerView)findViewById(R.id.myrecyclerview);
        linearLayoutManager =
                new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        myRecyclerViewAdapter = new RecyclerViewAdapter(this);
        myRecyclerViewAdapter.setOnItemClickListener(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(linearLayoutManager);

    }

    private void refresh(){

        final int pos = myRecyclerViewAdapter.getItemCount();
        myRecyclerViewAdapter.add(pos, "Refreshing...");
        swipeRefreshLayout.setRefreshing(true);

        //refresh long-time task in background thread
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //dummy delay for 2 second
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //update ui on UI thread
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        String currentDateTime =
                                DateFormat.getDateTimeInstance().format(new Date());

                        myRecyclerViewAdapter.set(pos, pos + " - " + currentDateTime);
                        swipeRefreshLayout.setRefreshing(false);
                    }
                });

            }
        }).start();
    }

    @Override
    public void onItemClick(RecyclerViewAdapter.ItemHolder item, int position) {
        Toast.makeText(this,
                position + " : " + item.getItemText(),
                Toast.LENGTH_SHORT).show();
    }
}



download filesDownload the files .

Saturday, November 28, 2015

RecyclerView + CardView example: with Button


This example work on last example of "Gallery-like RecyclerView + CardView example" to show how to add a button and OnClickListener in RecyclerView + CardView. A ImageButton is add over the photo on each cell. Once user click on the ImageButton, the corresponding OnClickListener, to show the info of the corresponding photo.


Modify layout/layout_cardview.xml to add a ImageButton.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    card_view:cardCornerRadius="5sp"
    card_view:cardElevation="5sp">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/item_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <ImageButton
            android:id="@+id/buttonInfo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@android:drawable/ic_menu_info_details"
            android:background="#00ffffff"/>

    </FrameLayout>
</android.support.v7.widget.CardView>


Modify MyRecyclerViewAdapter.java:
- get the reference to the Button in the constructor of RecyclerView.ViewHolder.
- implement the OnClickListener in onBindViewHolder() of MyRecyclerViewAdapter.
package com.blogspot.android_er.androidgallery;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemHolder>{

    private List<Uri> itemsUri;
    private LayoutInflater layoutInflater;
    private Context context;
    private OnItemClickListener onItemClickListener;
    MainActivity mainActivity;

    public MyRecyclerViewAdapter(Context context, MainActivity mainActivity){
        this.context = context;
        layoutInflater = LayoutInflater.from(context);
        itemsUri = new ArrayList<Uri>();

        this.mainActivity = mainActivity;
    }

    @Override
    public MyRecyclerViewAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        CardView itemCardView = (CardView)layoutInflater.inflate(R.layout.layout_cardview, parent, false);
        return new ItemHolder(itemCardView, this);
    }

    @Override
    public void onBindViewHolder(MyRecyclerViewAdapter.ItemHolder holder, final int position) {
        final Uri targetUri = itemsUri.get(position);
        holder.setItemUri(targetUri.getPath());

        if (targetUri != null){

            try {
                //! CAUTION !
                //I'm not sure is it properly to load bitmap here!
                holder.setImageView(loadScaledBitmap(targetUri));

                holder.btnInfo.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(context,
                                "btnInfo clicked:\n"
                                + "position:" + position + "\n"
                                + targetUri.getLastPathSegment(),
                                Toast.LENGTH_LONG).show();
                    }
                });

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

    /*
    reference:
    Load scaled bitmap
    http://android-er.blogspot.com/2013/08/load-scaled-bitmap.html
     */
    private Bitmap loadScaledBitmap(Uri src) throws FileNotFoundException {

        //display the file to be loadScaledBitmap(),
        //such that you can know how much work on it.
        mainActivity.textInfo.append(src.getLastPathSegment() + "\n");

        // required max width/height
        final int REQ_WIDTH = 150;
        final int REQ_HEIGHT = 150;

        Bitmap bm = null;

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(context.getContentResolver().openInputStream(src),
                null, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, REQ_WIDTH,
                REQ_HEIGHT);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        bm = BitmapFactory.decodeStream(
                context.getContentResolver().openInputStream(src), null, options);

        return bm;
    }

    public int calculateInSampleSize(BitmapFactory.Options options,
                                     int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            // Calculate ratios of height and width to requested height and
            // width
            final int heightRatio = Math.round((float) height
                    / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will
            // guarantee
            // a final image with both dimensions larger than or equal to the
            // requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }

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

    public void setOnItemClickListener(OnItemClickListener listener){
        onItemClickListener = listener;
    }

    public OnItemClickListener getOnItemClickListener(){
        return onItemClickListener;
    }

    public interface OnItemClickListener{
        public void onItemClick(ItemHolder item, int position);
    }

    public void add(int location, Uri iUri){
        itemsUri.add(location, iUri);
        notifyItemInserted(location);
    }

    public void clearAll(){
        int itemCount = itemsUri.size();

        if(itemCount>0){
            itemsUri.clear();
            notifyItemRangeRemoved(0, itemCount);
        }
    }


    public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        private MyRecyclerViewAdapter parent;
        private CardView cardView;
        ImageView imageView;
        String itemUri;

        ImageButton btnInfo;

        public ItemHolder(CardView cardView, MyRecyclerViewAdapter parent) {
            super(cardView);
            itemView.setOnClickListener(this);
            this.cardView = cardView;
            this.parent = parent;
            imageView = (ImageView) cardView.findViewById(R.id.item_image);
            btnInfo = (ImageButton) cardView.findViewById(R.id.buttonInfo);
        }

        public void setItemUri(String itemUri){
            this.itemUri = itemUri;
        }

        public String getItemUri(){
            return itemUri;
        }

        public void setImageView(Bitmap bitmap){
            imageView.setImageBitmap(bitmap);
        }

        @Override
        public void onClick(View v) {
            final OnItemClickListener listener = parent.getOnItemClickListener();
            if(listener != null){
                listener.onItemClick(this, getLayoutPosition());
                //or use
                //listener.onItemClick(this, getAdapterPosition());
            }
        }
    }
}




~ More example of RecyclerView + CardView.


Friday, November 13, 2015

Gallery-like RecyclerView + CardView example


A long long time ago, we have android.widget.Gallery to shows items (ex. photos) in a center-locked, horizontally scrolling list. My example "Implement Android Gallery widget". But it deprecated and no longer supported.

So in long time ago at 2012, I have another example to "Implement Gallery-like HorizontalScrollView".

Now, with RecyclerView and CardView, it's another example to implement Gallery-like RecyclerView + CardView. It display files in ExternalStorageDirectoryPath + "/test/" folder.
(If you want to load from other user selectable folder, refer "Intent.ACTION_OPEN_DOCUMENT (from API level 19) to load images in RecyclerView + CardView".)


To use RecyclerView + CardView, we have to "Add Support Libraries of RecyclerView, CardView to Android Studio Project".

Create our RecyclerView.Adapter, MyRecyclerViewAdapter.java
package com.blogspot.android_er.androidgallery;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemHolder>{

    private List<Uri> itemsUri;
    private LayoutInflater layoutInflater;
    private Context context;
    private OnItemClickListener onItemClickListener;
    MainActivity mainActivity;

    public MyRecyclerViewAdapter(Context context, MainActivity mainActivity){
        this.context = context;
        layoutInflater = LayoutInflater.from(context);
        itemsUri = new ArrayList<Uri>();

        this.mainActivity = mainActivity;
    }

    @Override
    public MyRecyclerViewAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        CardView itemCardView = (CardView)layoutInflater.inflate(R.layout.layout_cardview, parent, false);
        return new ItemHolder(itemCardView, this);
    }

    @Override
    public void onBindViewHolder(MyRecyclerViewAdapter.ItemHolder holder, int position) {
        Uri targetUri = itemsUri.get(position);
        holder.setItemUri(targetUri.getPath());

        if (targetUri != null){

            try {
                //! CAUTION !
                //I'm not sure is it properly to load bitmap here!
                holder.setImageView(loadScaledBitmap(targetUri));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    /*
    reference:
    Load scaled bitmap
    http://android-er.blogspot.com/2013/08/load-scaled-bitmap.html
     */
    private Bitmap loadScaledBitmap(Uri src) throws FileNotFoundException {

        //display the file to be loadScaledBitmap(),
        //such that you can know how much work on it.
        mainActivity.textInfo.append(src.getLastPathSegment() + "\n");

        // required max width/height
        final int REQ_WIDTH = 150;
        final int REQ_HEIGHT = 150;

        Bitmap bm = null;

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(context.getContentResolver().openInputStream(src),
                null, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, REQ_WIDTH,
                REQ_HEIGHT);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        bm = BitmapFactory.decodeStream(
                context.getContentResolver().openInputStream(src), null, options);

        return bm;
    }

    public int calculateInSampleSize(BitmapFactory.Options options,
                                     int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            // Calculate ratios of height and width to requested height and
            // width
            final int heightRatio = Math.round((float) height
                    / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will
            // guarantee
            // a final image with both dimensions larger than or equal to the
            // requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }

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

    public void setOnItemClickListener(OnItemClickListener listener){
        onItemClickListener = listener;
    }

    public OnItemClickListener getOnItemClickListener(){
        return onItemClickListener;
    }

    public interface OnItemClickListener{
        public void onItemClick(ItemHolder item, int position);
    }

    public void add(int location, Uri iUri){
        itemsUri.add(location, iUri);
        notifyItemInserted(location);
    }

    public void clearAll(){
        int itemCount = itemsUri.size();

        if(itemCount>0){
            itemsUri.clear();
            notifyItemRangeRemoved(0, itemCount);
        }
    }


    public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        private MyRecyclerViewAdapter parent;
        private CardView cardView;
        ImageView imageView;
        String itemUri;

        public ItemHolder(CardView cardView, MyRecyclerViewAdapter parent) {
            super(cardView);
            itemView.setOnClickListener(this);
            this.cardView = cardView;
            this.parent = parent;
            imageView = (ImageView) cardView.findViewById(R.id.item_image);
        }

        public void setItemUri(String itemUri){
            this.itemUri = itemUri;
        }

        public String getItemUri(){
            return itemUri;
        }

        public void setImageView(Bitmap bitmap){
            imageView.setImageBitmap(bitmap);
        }

        @Override
        public void onClick(View v) {
            final OnItemClickListener listener = parent.getOnItemClickListener();
            if(listener != null){
                listener.onItemClick(this, getLayoutPosition());
                //or use
                //listener.onItemClick(this, getAdapterPosition());
            }
        }
    }
}


layout/layout_cardview.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    card_view:cardCornerRadius="5sp"
    card_view:cardElevation="5sp">

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

        <ImageView
            android:id="@+id/item_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>
</android.support.v7.widget.CardView>


MainActivity.java
package com.blogspot.android_er.androidgallery;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;

public class MainActivity extends AppCompatActivity
        implements MyRecyclerViewAdapter.OnItemClickListener{

    private RecyclerView myRecyclerView;
    private MyRecyclerViewAdapter myRecyclerViewAdapter;
    private LinearLayoutManager linearLayoutManager;

    TextView textInfo;

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

        textInfo = (TextView)findViewById(R.id.info);
        textInfo.setMovementMethod(new ScrollingMovementMethod());

        myRecyclerView = (RecyclerView)findViewById(R.id.myrecyclerview);
        linearLayoutManager =
                new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        myRecyclerViewAdapter = new MyRecyclerViewAdapter(this, this);
        myRecyclerViewAdapter.setOnItemClickListener(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(linearLayoutManager);

        prepareGallery();
    }

    private void prepareGallery(){
        String ExternalStorageDirectoryPath = Environment
                .getExternalStorageDirectory()
                .getAbsolutePath();
        String targetPath = ExternalStorageDirectoryPath + "/test/";

        Toast.makeText(getApplicationContext(), targetPath, Toast.LENGTH_LONG).show();
        File targetDirector = new File(targetPath);

        File[] files = targetDirector.listFiles();
        for (File file : files){
            Uri uri = Uri.fromFile(file);
            myRecyclerViewAdapter.add(
                    myRecyclerViewAdapter.getItemCount(),
                    uri);
        }
    }

    @Override
    public void onItemClick(MyRecyclerViewAdapter.ItemHolder item, int position) {

        String stringitemUri = item.getItemUri();
        Toast.makeText(MainActivity.this, stringitemUri, Toast.LENGTH_SHORT).show();
    }
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/myrecyclerview"
        android:layout_width="match_parent"
        android:layout_height="170dp" />

    <TextView
        android:id="@+id/info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:typeface="monospace"
        android:gravity="bottom"/>

</LinearLayout>


To read diles in ExternalStorage, uses-permission of "android.permission.READ_EXTERNAL_STORAGE" is needed in AndroidManifest.xml.

download filesDownload the files (Android Studio Format) .

Next:
RecyclerView + CardView example: with Button

~ More example of RecyclerView + CardView.


Monday, September 7, 2015

Intent.ACTION_OPEN_DOCUMENT to load images in RecyclerView + CardView

Last exercise show how to "Open multi files using Intent.ACTION_OPEN_DOCUMENT, with EXTRA_ALLOW_MULTIPLE and getClipData()". Here modify to load returned images in RecyclerView + CardView.



To use RecyclerView + CardView, we have to "Add Support Libraries of RecyclerView, CardView to Android Studio Project".

layout/layout_cardview.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    card_view:cardCornerRadius="20sp"
    card_view:cardElevation="5sp">

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

        <ImageView
            android:id="@+id/item_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/item_uri"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18dp"/>

    </LinearLayout>

</android.support.v7.widget.CardView>


com.blogspot.android_er.android_action_open_document.MyRecyclerViewAdapter.java
package com.blogspot.android_er.android_action_open_document;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

public class MyRecyclerViewAdapter extends
        RecyclerView.Adapter<MyRecyclerViewAdapter.ItemHolder>{

    private List<Uri> itemsUri;
    private LayoutInflater layoutInflater;
    private Context context;

    public MyRecyclerViewAdapter(Context context){
        this.context = context;
        layoutInflater = LayoutInflater.from(context);
        itemsUri = new ArrayList<Uri>();
    }

    @Override
    public ItemHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        CardView itemCardView = (CardView)layoutInflater.inflate(R.layout.layout_cardview, viewGroup, false);
        return new ItemHolder(itemCardView, this);
    }

    @Override
    public void onBindViewHolder(ItemHolder itemHolder, int i) {

        Uri targetUri = itemsUri.get(i);
        itemHolder.setItemUri(targetUri.getPath());

        if (targetUri != null){

            try {
                //! CAUTION !
                //I'm not sure is it properly to load bitmap here!
                itemHolder.setImageView(loadScaledBitmap(targetUri));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    /*
    reference:
    Load scaled bitmap
    http://android-er.blogspot.com/2013/08/load-scaled-bitmap.html
     */
    private Bitmap loadScaledBitmap(Uri src) throws FileNotFoundException {

        // required max width/height
        final int REQ_WIDTH = 400;
        final int REQ_HEIGHT = 400;

        Bitmap bm = null;

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(context.getContentResolver().openInputStream(src),
                null, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, REQ_WIDTH,
                REQ_HEIGHT);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        bm = BitmapFactory.decodeStream(
                context.getContentResolver().openInputStream(src), null, options);

        return bm;
    }

    public int calculateInSampleSize(BitmapFactory.Options options,
                                     int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            // Calculate ratios of height and width to requested height and
            // width
            final int heightRatio = Math.round((float) height
                    / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will
            // guarantee
            // a final image with both dimensions larger than or equal to the
            // requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }

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

    public void add(int location, Uri iUri){
        itemsUri.add(location, iUri);
        notifyItemInserted(location);
    }

    public void clearAll(){
        int itemCount = itemsUri.size();

        if(itemCount>0){
            itemsUri.clear();
            notifyItemRangeRemoved(0, itemCount);
        }
    }

    public static class ItemHolder extends RecyclerView.ViewHolder{

        private MyRecyclerViewAdapter parent;
        private CardView cardView;
        TextView textItemUri;
        ImageView imageView;

        public ItemHolder(CardView cView, MyRecyclerViewAdapter parent) {
            super(cView);
            cardView = cView;
            this.parent = parent;
            textItemUri = (TextView) cardView.findViewById(R.id.item_uri);
            imageView = (ImageView) cardView.findViewById(R.id.item_image);
        }

        public void setItemUri(CharSequence name){
            textItemUri.setText(name);
        }

        public void setImageView(Bitmap bitmap){
            imageView.setImageBitmap(bitmap);
        }

    }
}


layout/activity_main.xml
<LinearLayout
    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"
    android:padding="10dp"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/opendocument"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Open Document of Image/Video" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/myrecyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>


com.blogspot.android_er.android_action_open_document.MainActivity.java
package com.blogspot.android_er.android_action_open_document;

import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final int RQS_OPEN = 1;

    Button buttonOpen;

    private RecyclerView myRecyclerView;
    private StaggeredGridLayoutManager staggeredGridLayoutManagerVertical;
    private MyRecyclerViewAdapter myRecyclerViewAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        buttonOpen = (Button) findViewById(R.id.opendocument);
        buttonOpen.setOnClickListener(buttonOpenOnClickListener);

        myRecyclerView = (RecyclerView)findViewById(R.id.myrecyclerview);
        staggeredGridLayoutManagerVertical =
                new StaggeredGridLayoutManager(
                        2, //The number of Columns in the grid
                        LinearLayoutManager.VERTICAL);
        myRecyclerViewAdapter = new MyRecyclerViewAdapter(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(staggeredGridLayoutManagerVertical);
    }

    View.OnClickListener buttonOpenOnClickListener =
            new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    //Open multi-type using Intent.ACTION_OPEN_DOCUMENT
                    //Open multi-file
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
                    intent.addCategory(Intent.CATEGORY_OPENABLE);
                    intent.setType("image/*");
                    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                    startActivityForResult(intent, RQS_OPEN);

                    Toast.makeText(MainActivity.this,
                            "Single-selection: Tap on any file.\n" +
                                    "Multi-selection: Tap & Hold on the first file, " +
                                    "tap for more, tap on OPEN to finish.",
                            Toast.LENGTH_LONG).show();
                }
            };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        myRecyclerViewAdapter.clearAll();

        if (resultCode == RESULT_OK) {
            if (requestCode == RQS_OPEN) {
                ClipData clipData = data.getClipData();
                if(clipData == null){
                    myRecyclerViewAdapter.add(
                            myRecyclerViewAdapter.getItemCount(),
                            data.getData());
                }else{
                    for(int i=0; i<clipData.getItemCount(); i++){
                        ClipData.Item item = clipData.getItemAt(i);
                        Uri uri = item.getUri();
                        //s += uri.toString() + "\n";
                        myRecyclerViewAdapter.add(
                                myRecyclerViewAdapter.getItemCount(),
                                uri);
                    }
                }

            }
        }
    }
}



download filesDownload the files (Android Studio Format) .


How it run on Bluestacks App Player, refer: "Install Bluestacks App Player on Windows 10, and test your app".



More example:
- for Intent.ACTION_OPEN_DOCUMENT 
- for RecyclerView + CardView

Tuesday, September 1, 2015

RecyclerView + CardView example - list system properties using System.getProperties()

My former example show how to "Retrieve system properties using System.getProperties()", here we are going to list the Properties on RecyclerView + CardView, similar to another example "RecyclerView + CardView example with ImageView - list available Drawable".


To use RecyclerView + CardView, we have to "Add Support Libraries of RecyclerView, CardView to Android Studio Project".

layout/layout_cardview.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    card_view:cardCornerRadius="5sp"
    card_view:cardElevation="5sp">

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

        <TextView
            android:id="@+id/item_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14dp" />

        <TextView
            android:id="@+id/item_value"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textSize="16dp" />

    </LinearLayout>

</android.support.v7.widget.CardView>


com.blogspot.android_er.androidproperties.MyRecyclerViewAdapter.java
package com.blogspot.android_er.androidproperties;

import android.content.Context;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MyRecyclerViewAdapter extends
        RecyclerView.Adapter<MyRecyclerViewAdapter.ItemHolder>{

    private List<String> itemsName;
    private List<String> itemsValue;
    private LayoutInflater layoutInflater;
    private Context context;

    public MyRecyclerViewAdapter(Context context){
        this.context = context;
        layoutInflater = LayoutInflater.from(context);
        itemsName = new ArrayList<String>();
        itemsValue = new ArrayList<String>();
    }

    @Override
    public ItemHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        CardView itemCardView =
                (CardView)layoutInflater.inflate(R.layout.layout_cardview, viewGroup, false);
        return new ItemHolder(itemCardView, this);
    }

    @Override
    public void onBindViewHolder(ItemHolder itemHolder, int i) {
        itemHolder.setItemName(itemsName.get(i));
        String value = itemsValue.get(i);
        itemHolder.setItemValue(String.valueOf(value));
    }

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

    public void add(int location, String iName, String iValue){
        itemsName.add(location, iName);
        itemsValue.add(location, iValue);
        notifyItemInserted(location);
    }

    public void remove(int location){
        if(location >= itemsName.size())
            return;

        itemsName.remove(location);
        itemsValue.remove(location);
        notifyItemRemoved(location);
    }

    public static class ItemHolder extends RecyclerView.ViewHolder{

        private MyRecyclerViewAdapter parent;
        private CardView cardView;
        TextView textItemName;
        TextView textItemValue;

        public ItemHolder(CardView cView, MyRecyclerViewAdapter parent) {
            super(cView);
            cardView = cView;
            this.parent = parent;
            textItemName = (TextView) cardView.findViewById(R.id.item_name);
            textItemValue = (TextView) cardView.findViewById(R.id.item_value);
        }

        public void setItemName(CharSequence name){
            textItemName.setText(name);
        }

        public CharSequence getItemName(){
            return textItemName.getText();
        }

        public void setItemValue(CharSequence val){
            textItemValue.setText(val);
        }

        public CharSequence getItemValue(){
            return textItemValue.getText();
        }
    }
}


layout/activity_main.xml
<LinearLayout 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"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/myrecyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>


com.blogspot.android_er.androidproperties.MainActivity.java
package com.blogspot.android_er.androidproperties;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.Enumeration;
import java.util.Properties;

public class MainActivity extends AppCompatActivity {

    private RecyclerView myRecyclerView;
    LinearLayoutManager linearLayoutManager;
    private MyRecyclerViewAdapter myRecyclerViewAdapter;

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

        myRecyclerView = (RecyclerView)findViewById(R.id.myrecyclerview);

        linearLayoutManager =
                new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        myRecyclerViewAdapter = new MyRecyclerViewAdapter(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(linearLayoutManager);

        prepareItems();
    }

    private void prepareItems(){

        Properties properties = System.getProperties();
        Enumeration<String> prop =
                (Enumeration<String>) properties.propertyNames();

        while(prop.hasMoreElements()){
            String propName = prop.nextElement();

            myRecyclerViewAdapter.add(
                    myRecyclerViewAdapter.getItemCount(),
                    propName,
                    System.getProperty(propName));
        }
    }
}


Tested on Nexus 7 running Android 5.1.1

Tested on Android Emulator running Android 6

download filesDownload the files (Android Studio Format) .

~ More step-by-step examples of RecyclerView + CardView.

Thursday, August 20, 2015

RecyclerView + CardView example with ImageView - list available Drawable

Last post show how to "get all available drawable and its value". This example show how to display the drawables, names and values in RecyclerView + CardView.


To use RecyclerView + CardView, we have to "Add Support Libraries of RecyclerView, CardView to Android Studio Project".

Create layout of the CardView, layout/layout_cardview.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    card_view:cardCornerRadius="20sp"
    card_view:cardElevation="5sp">

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

        <ImageView
            android:id="@+id/item_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/item_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18dp"/>
        <TextView
            android:id="@+id/item_value"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="16dp"/>

    </LinearLayout>

</android.support.v7.widget.CardView>


Create our custom MyRecyclerViewAdapter extends RecyclerView.Adapter, com.example.androidlistdrawable.MyRecyclerViewAdapter.java
package com.example.androidlistdrawable;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MyRecyclerViewAdapter extends
        RecyclerView.Adapter<MyRecyclerViewAdapter.ItemHolder> {

    private List<String> itemsName;
    private List<Integer> itemsValue;
    private LayoutInflater layoutInflater;
    private Context context;

    public MyRecyclerViewAdapter(Context context){
        this.context = context;
        layoutInflater = LayoutInflater.from(context);
        itemsName = new ArrayList<String>();
        itemsValue = new ArrayList<Integer>();
    }

    @Override
    public MyRecyclerViewAdapter.ItemHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        CardView itemCardView = (CardView)layoutInflater.inflate(R.layout.layout_cardview, viewGroup, false);
        return new ItemHolder(itemCardView, this);
    }

    @Override
    public void onBindViewHolder(MyRecyclerViewAdapter.ItemHolder itemHolder, int i) {
        itemHolder.setItemName(itemsName.get(i));
        int value = itemsValue.get(i);
        itemHolder.setItemValue(String.valueOf(value));
        Drawable drawable = context.getResources().getDrawable(value);
        itemHolder.setImageView(drawable);
    }

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

    public void add(int location, String iName, int iValue){
        itemsName.add(location, iName);
        itemsValue.add(location, iValue);
        notifyItemInserted(location);
    }

    public void remove(int location){
        if(location >= itemsName.size())
            return;

        itemsName.remove(location);
        itemsValue.remove(location);
        notifyItemRemoved(location);
    }

    public static class ItemHolder extends RecyclerView.ViewHolder{

        private MyRecyclerViewAdapter parent;
        private CardView cardView;
        TextView textItemName;
        TextView textItemValue;
        ImageView imageView;

        public ItemHolder(CardView cView, MyRecyclerViewAdapter parent) {
            super(cView);
            cardView = cView;
            this.parent = parent;
            textItemName = (TextView) cardView.findViewById(R.id.item_name);
            textItemValue = (TextView) cardView.findViewById(R.id.item_value);
            imageView = (ImageView) cardView.findViewById(R.id.item_image);
        }

        public void setItemName(CharSequence name){
            textItemName.setText(name);
        }

        public CharSequence getItemName(){
            return textItemName.getText();
        }

        public void setItemValue(CharSequence val){
            textItemValue.setText(val);
        }

        public CharSequence getItemValue(){
            return textItemValue.getText();
        }

        public void setImageView(Drawable drawable){
            imageView.setImageDrawable(drawable);
        }

    }
}


Modify layout to add RecyclerView, layout/activity_main.xml.
<LinearLayout
    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"
    android:padding="10dp"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/myrecyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>


com.example.androidlistdrawable.MainActivity.java
package com.example.androidlistdrawable;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;

import java.lang.reflect.Field;

public class MainActivity extends AppCompatActivity {

    private RecyclerView myRecyclerView;
    private StaggeredGridLayoutManager staggeredGridLayoutManagerVertical;
    private MyRecyclerViewAdapter myRecyclerViewAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myRecyclerView = (RecyclerView)findViewById(R.id.myrecyclerview);

        staggeredGridLayoutManagerVertical =
                new StaggeredGridLayoutManager(
                        2, //The number of Columns in the grid
                        LinearLayoutManager.VERTICAL);
        myRecyclerViewAdapter = new MyRecyclerViewAdapter(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(staggeredGridLayoutManagerVertical);

        prepareItems();
    }

    private void prepareItems(){
        Field[] fieldDrawables = android.R.drawable.class.getFields();
        for(int i=0; i<fieldDrawables.length; i++){
            Field field = fieldDrawables[i];
            try {
                int value = (int) field.get(fieldDrawables);
                myRecyclerViewAdapter.add(
                        myRecyclerViewAdapter.getItemCount(),
                        "R.drawable." + field.getName(),
                        value);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }
    }

}




download filesDownload the files (Android Studio Format).


~ More step-by-step examples of RecyclerView + CardView.

Sunday, July 26, 2015

StaggeredGridLayoutManager on RecyclerView


android.support.v7.widget.StaggeredGridLayoutManager is a LayoutManager that lays out children in a staggered grid formation. It supports horizontal & vertical layout as well as an ability to layout children in reverse.

Example to create StaggeredGridLayoutManager:
        staggeredGridLayoutManagerVertical =
                new StaggeredGridLayoutManager(
                        2, //The number of Columns in the grid
                        LinearLayoutManager.VERTICAL);
        staggeredGridLayoutManagerHorizontal =
                new StaggeredGridLayoutManager(
                        3, //The number of rows in the grid
                        LinearLayoutManager.HORIZONTAL);


Modify last example "Android example using RecyclerView with CardView":

layout/activity_main.xml
<LinearLayout 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"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <EditText
            android:id="@+id/namefield"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/addbutton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Add"/>

        <RadioGroup
            android:id="@+id/optGroupLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
            <RadioButton
                android:id="@+id/optLinearLayoutVertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="LinearLayout Vertical"
                android:checked="true" />
            <RadioButton
                android:id="@+id/optLinearLayoutHorizontal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="LinearLayout Horizontal" />
            <RadioButton
                android:id="@+id/optGridLayoutVertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="GridLayout Vertical" />
            <RadioButton
                android:id="@+id/optGridLayoutHorizontal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="GridLayout Horizontal" />
            <RadioButton
                android:id="@+id/optStaggeredGridLayoutVertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="StaggeredGridLayout Vertical" />
            <RadioButton
                android:id="@+id/optStaggeredGridLayoutHorizontal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="StaggeredGridLayout Horizontal" />
        </RadioGroup>
    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/myrecyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>


com.example.androidrecyclerview.MainActivity.java
package com.example.androidrecyclerview;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity implements RecyclerViewAdapter.OnItemClickListener{

    private RecyclerView myRecyclerView;
    private RecyclerViewAdapter myRecyclerViewAdapter;

    EditText nameField;
    Button btnAdd;

    RadioGroup optGroupLayout;
    RadioButton optLinearLayoutHorizontal;
    RadioButton optLinearLayoutVertical;
    RadioButton optGridLayoutHorizontal;
    RadioButton optGridLayoutVertical;
    RadioButton optStaggeredGridLayoutHorizontal;
    RadioButton optStaggeredGridLayoutVertical;

    private LinearLayoutManager linearLayoutManagerVertical;
    private LinearLayoutManager linearLayoutManagerHorizontal;
    private GridLayoutManager gridLayoutManagerVertical;
    private GridLayoutManager gridLayoutManagerHorizontal;
    private StaggeredGridLayoutManager staggeredGridLayoutManagerVertical;
    private StaggeredGridLayoutManager staggeredGridLayoutManagerHorizontal;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myRecyclerView = (RecyclerView)findViewById(R.id.myrecyclerview);

        linearLayoutManagerVertical =
                new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        linearLayoutManagerHorizontal =
                new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        gridLayoutManagerVertical =
                new GridLayoutManager(this,
                        2, //The number of Columns in the grid
                        LinearLayoutManager.VERTICAL,
                        false);
        gridLayoutManagerHorizontal =
                new GridLayoutManager(this,
                        3, //The number of rows in the grid
                        LinearLayoutManager.HORIZONTAL,
                        false);

        staggeredGridLayoutManagerVertical =
                new StaggeredGridLayoutManager(
                        2, //The number of Columns in the grid
                        LinearLayoutManager.VERTICAL);
        staggeredGridLayoutManagerHorizontal =
                new StaggeredGridLayoutManager(
                        3, //The number of rows in the grid
                        LinearLayoutManager.HORIZONTAL);

        //set SpanSizeLookup()
        gridLayoutManagerVertical.setSpanSizeLookup(new MySpanSizeLookup(5, 1, 2));
        gridLayoutManagerHorizontal.setSpanSizeLookup(new MySpanSizeLookup(4, 1, 3));

        myRecyclerViewAdapter = new RecyclerViewAdapter(this);
        myRecyclerViewAdapter.setOnItemClickListener(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(linearLayoutManagerVertical);

        //Add MyItemDecoration
        myRecyclerView.addItemDecoration(new MyItemDecoration(this));

        nameField = (EditText)findViewById(R.id.namefield);
        btnAdd = (Button)findViewById(R.id.addbutton);
        btnAdd.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String newName = nameField.getText().toString();

                if(!newName.equals("")){
                    if(myRecyclerViewAdapter.getItemCount()>1){
                        myRecyclerViewAdapter.add(1, newName);
                    }else{
                        myRecyclerViewAdapter.add(0, newName);
                    }
                }
            }
        });

        optGroupLayout = (RadioGroup)findViewById(R.id.optGroupLayout);
        optLinearLayoutHorizontal = (RadioButton)findViewById(R.id.optLinearLayoutHorizontal);
        optLinearLayoutVertical = (RadioButton)findViewById(R.id.optLinearLayoutVertical);
        optGridLayoutHorizontal = (RadioButton)findViewById(R.id.optGridLayoutHorizontal);
        optGridLayoutVertical = (RadioButton)findViewById(R.id.optGridLayoutVertical);
        optStaggeredGridLayoutHorizontal = (RadioButton)findViewById(R.id.optStaggeredGridLayoutHorizontal);
        optStaggeredGridLayoutVertical = (RadioButton)findViewById(R.id.optStaggeredGridLayoutVertical);
        optGroupLayout.setOnCheckedChangeListener(optLayoutCheckedChangeListener);

        //pre-load dummy items
        myRecyclerViewAdapter.add(0, "SpanSizeLookup");
        myRecyclerViewAdapter.add(0, "ItemDecoration");
        myRecyclerViewAdapter.add(0, "GridLayoutManager");
        myRecyclerViewAdapter.add(0, "LinearLayoutManager");
        myRecyclerViewAdapter.add(0, "RecyclerViewAdapter");
        myRecyclerViewAdapter.add(0, "RecyclerView example");
        myRecyclerViewAdapter.add(0, "RecyclerView");
        myRecyclerViewAdapter.add(0, "android-er.blogspot.com");
        myRecyclerViewAdapter.add(0, "android-er");
        myRecyclerViewAdapter.add(0, "android");

    }

    private RadioGroup.OnCheckedChangeListener optLayoutCheckedChangeListener =
            new RadioGroup.OnCheckedChangeListener(){
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId) {
                    if(optLinearLayoutVertical.isChecked()){
                        myRecyclerView.setLayoutManager(linearLayoutManagerVertical);
                    }else if(optLinearLayoutHorizontal.isChecked()){
                        myRecyclerView.setLayoutManager(linearLayoutManagerHorizontal);
                    }else if(optGridLayoutHorizontal.isChecked()){
                        myRecyclerView.setLayoutManager(gridLayoutManagerHorizontal);
                    }else if(optGridLayoutVertical.isChecked()){
                        myRecyclerView.setLayoutManager(gridLayoutManagerVertical);
                    }else if(optStaggeredGridLayoutHorizontal.isChecked()){
                        myRecyclerView.setLayoutManager(staggeredGridLayoutManagerHorizontal);
                    }else if(optStaggeredGridLayoutVertical.isChecked()){
                        myRecyclerView.setLayoutManager(staggeredGridLayoutManagerVertical);
                    }
                }
            };


    @Override
    public void onItemClick(RecyclerViewAdapter.ItemHolder item, int position) {
        Toast.makeText(this,
                "Remove " + position + " : " + item.getItemName(),
                Toast.LENGTH_SHORT).show();
        myRecyclerViewAdapter.remove(position);
    }
}



download filesDownload the files (Android Studio Format).


- More step-by-step examples of RecyclerView.

Friday, July 24, 2015

Android example using RecyclerView with CardView

The former post show "Android CardView example", It can be embedded in RecyclerView.



Modify from last exercise of RecyclerView, "onDraw() and onDrawOver() of ItemDecoration for RecyclerView".

Create layout of the CardView, layout/layout_cardview.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    card_view:cardCornerRadius="20sp"
    card_view:cardElevation="5sp">

    <TextView
        android:id="@+id/card_item_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="40dp"/>

</android.support.v7.widget.CardView>

Modify constructor of ItemHolder() in com.example.androidrecyclerview.RecyclerViewAdapter.java, ItemHolder(CardView cView, RecyclerViewAdapter parent), to include CardView. And also modify the method onCreateViewHolder(ViewGroup parent, int viewType).

com.example.androidrecyclerview.RecyclerViewAdapter.java
package com.example.androidrecyclerview;

import android.content.Context;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ItemHolder> {

    private List<String> itemsName;
    private OnItemClickListener onItemClickListener;
    private LayoutInflater layoutInflater;

    public RecyclerViewAdapter(Context context){
        layoutInflater = LayoutInflater.from(context);
        itemsName = new ArrayList<String>();
    }

    @Override
    public RecyclerViewAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //View itemView = layoutInflater.inflate(R.layout.layout_item, parent, false);
        //return new ItemHolder(itemView, this);
        CardView itemCardView = (CardView)layoutInflater.inflate(R.layout.layout_cardview, parent, false);
        return new ItemHolder(itemCardView, this);
    }

    @Override
    public void onBindViewHolder(RecyclerViewAdapter.ItemHolder holder, int position) {
        holder.setItemName(itemsName.get(position));
    }

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

    public void setOnItemClickListener(OnItemClickListener listener){
        onItemClickListener = listener;
    }

    public OnItemClickListener getOnItemClickListener(){
        return onItemClickListener;
    }

    public interface OnItemClickListener{
        public void onItemClick(ItemHolder item, int position);
    }

    public void add(int location, String iName){
        itemsName.add(location, iName);
        notifyItemInserted(location);
    }

    public void remove(int location){
        if(location >= itemsName.size())
            return;

        itemsName.remove(location);
        notifyItemRemoved(location);
    }

    public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        private RecyclerViewAdapter parent;
        TextView textItemName;

        private CardView cardView;

        /*
        public ItemHolder(View itemView, RecyclerViewAdapter parent) {
            super(itemView);
            itemView.setOnClickListener(this);
            this.parent = parent;
            textItemName = (TextView) itemView.findViewById(R.id.item_name);
        }
        */

        public ItemHolder(CardView cView, RecyclerViewAdapter parent) {
            super(cView);
            cardView = cView;
            cardView.setOnClickListener(this);
            this.parent = parent;
            textItemName = (TextView) cardView.findViewById(R.id.card_item_name);
        }

        public void setItemName(CharSequence name){
            textItemName.setText(name);
        }

        public CharSequence getItemName(){
            return textItemName.getText();
        }

        @Override
        public void onClick(View v) {
            final OnItemClickListener listener = parent.getOnItemClickListener();
            if(listener != null){
                listener.onItemClick(this, getPosition());
            }
        }
    }
}


download filesDownload the files (Android Studio Format).

Next:
- StaggeredGridLayoutManager (Google+ App-like) on RecyclerView


- More step-by-step examples of RecyclerView.

Tuesday, July 21, 2015

onDraw() and onDrawOver() of ItemDecoration for RecyclerView


In the exercise of "Implement custom ItemDecoration for RecyclerView" we already implement our ItemDecoration to draw lines on items in RecyclerView, in onDraw() method. Further work on last exercise "set SpanSizeLookup to GridLayoutManager of RecyclerView", here we do more:
- draw Border on canvas of whole RecyclerView, in onDraw()
- draw a enlarged bitmap on low-right corner of RecyclerView, in onDrawOver()


com.example.androidrecyclerview.MyItemDecoration.java
package com.example.androidrecyclerview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class MyItemDecoration extends RecyclerView.ItemDecoration{

    private Paint paintBlue, paintRed, paintBorder;
    private int offset;

    Bitmap bitmap;
    int bitmap_w, bitmap_h;
    Rect rectSrc;

    public MyItemDecoration(Context c){
        offset = 10;
        paintBlue = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintBlue.setColor(Color.BLUE);
        paintBlue.setStyle(Paint.Style.STROKE);
        paintBlue.setStrokeWidth(3);

        paintRed = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintRed.setColor(Color.RED);
        paintRed.setStyle(Paint.Style.STROKE);
        paintRed.setStrokeWidth(1);

        paintBorder = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintBorder.setColor(Color.GREEN);
        paintBorder.setStyle(Paint.Style.STROKE);
        paintBorder.setStrokeWidth(10);

        bitmap = BitmapFactory.decodeResource(
                c.getResources(),
                android.R.drawable.ic_menu_info_details);
        bitmap_w = bitmap.getWidth();
        bitmap_h = bitmap.getHeight();
        rectSrc = new Rect(0, 0, bitmap_w, bitmap_h);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        outRect.set(offset, offset, offset, offset);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);

        final RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();

        c.drawRect(
                0,
                0,
                c.getWidth(),
                c.getHeight(),
                paintBorder);

        for(int i=0; i<parent.getChildCount(); i++){
            final View child = parent.getChildAt(i);
            c.drawRect(
                    layoutManager.getDecoratedLeft(child),
                    layoutManager.getDecoratedTop(child),
                    layoutManager.getDecoratedRight(child),
                    layoutManager.getDecoratedBottom(child),
                    paintBlue);
            c.drawRect(
                    layoutManager.getDecoratedLeft(child) + offset,
                    layoutManager.getDecoratedTop(child) + offset,
                    layoutManager.getDecoratedRight(child) - offset,
                    layoutManager.getDecoratedBottom(child) - offset,
                    paintRed);

        }

    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
        c.drawBitmap(bitmap,
                rectSrc,
                new Rect(
                        c.getWidth()-(2*bitmap_w),
                        c.getHeight()-(2*bitmap_h),
                        c.getWidth(),
                        c.getHeight()),
                null);
    }
}


Have to modify constructor call of MyItemDecoration in MainActivity.java, such that we can get Resources drawable in MyItemDecoration.

        myRecyclerView.addItemDecoration(new MyItemDecoration());
to:
        myRecyclerView.addItemDecoration(new MyItemDecoration(this));

download filesDownload the files (Android Studio Format).

Next:
Android example using RecyclerView with CardView


- More step-by-step examples of RecyclerView.

Monday, July 20, 2015

set SpanSizeLookup to GridLayoutManager of RecyclerView

GridLayoutManager.SpanSizeLookup help to provide the number of spans each item of RecyclerView to occupies. Call setSpanSizeLookup(GridLayoutManager.SpanSizeLookup) method of GridLayoutManager to apply it.




This example modify from last exercise of "LinearLayoutManager and GridLayoutManager for RecyclerView". Create own custom GridLayoutManager.SpanSizeLookup, com.example.androidrecyclerview.MySpanSizeLookup.java
package com.example.androidrecyclerview;

import android.support.v7.widget.GridLayoutManager;

public class MySpanSizeLookup extends GridLayoutManager.SpanSizeLookup {

    int spanPos, spanCnt1, spanCnt2;

    public MySpanSizeLookup(int spanPos, int spanCnt1, int spanCnt2) {
        super();
        this.spanPos = spanPos;
        this.spanCnt1 = spanCnt1;
        this.spanCnt2 = spanCnt2;
    }

    @Override
    public int getSpanSize(int position) {
        return (position % spanPos ==0 ? spanCnt2 : spanCnt1);
    }
}


Modify com.example.androidrecyclerview.MainActivity.java, in onCreate() to implement and set MySpanSizeLookup().
package com.example.androidrecyclerview;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity implements RecyclerViewAdapter.OnItemClickListener{

    private RecyclerView myRecyclerView;
    private RecyclerViewAdapter myRecyclerViewAdapter;

    EditText nameField;
    Button btnAdd;

    RadioGroup optGroupLayout;
    RadioButton optLinearLayoutHorizontal;
    RadioButton optLinearLayoutVertical;
    RadioButton optGridLayoutHorizontal;
    RadioButton optGridLayoutVertical;

    private LinearLayoutManager linearLayoutManagerVertical;
    private LinearLayoutManager linearLayoutManagerHorizontal;
    private GridLayoutManager gridLayoutManagerVertical;
    private GridLayoutManager gridLayoutManagerHorizontal;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myRecyclerView = (RecyclerView)findViewById(R.id.myrecyclerview);

        linearLayoutManagerVertical =
                new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        linearLayoutManagerHorizontal =
                new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        gridLayoutManagerVertical =
                new GridLayoutManager(this,
                        2, //The number of Columns in the grid
                        LinearLayoutManager.VERTICAL,
                        false);
        gridLayoutManagerHorizontal =
                new GridLayoutManager(this,
                        3, //The number of rows in the grid
                        LinearLayoutManager.HORIZONTAL,
                        false);

        //set SpanSizeLookup()
        gridLayoutManagerVertical.setSpanSizeLookup(new MySpanSizeLookup(5, 1, 2));
        gridLayoutManagerHorizontal.setSpanSizeLookup(new MySpanSizeLookup(4, 1, 3));

        myRecyclerViewAdapter = new RecyclerViewAdapter(this);
        myRecyclerViewAdapter.setOnItemClickListener(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(linearLayoutManagerVertical);

        //Add MyItemDecoration
        myRecyclerView.addItemDecoration(new MyItemDecoration());

        nameField = (EditText)findViewById(R.id.namefield);
        btnAdd = (Button)findViewById(R.id.addbutton);
        btnAdd.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String newName = nameField.getText().toString();

                if(!newName.equals("")){
                    if(myRecyclerViewAdapter.getItemCount()>1){
                        myRecyclerViewAdapter.add(1, newName);
                    }else{
                        myRecyclerViewAdapter.add(0, newName);
                    }
                }
            }
        });

        optGroupLayout = (RadioGroup)findViewById(R.id.optGroupLayout);
        optLinearLayoutHorizontal = (RadioButton)findViewById(R.id.optLinearLayoutHorizontal);
        optLinearLayoutVertical = (RadioButton)findViewById(R.id.optLinearLayoutVertical);
        optGridLayoutHorizontal = (RadioButton)findViewById(R.id.optGridLayoutHorizontal);
        optGridLayoutVertical = (RadioButton)findViewById(R.id.optGridLayoutVertical);
        optGroupLayout.setOnCheckedChangeListener(optLayoutCheckedChangeListener);

        //pre-load dummy items
        myRecyclerViewAdapter.add(0, "SpanSizeLookup");
        myRecyclerViewAdapter.add(0, "ItemDecoration");
        myRecyclerViewAdapter.add(0, "GridLayoutManager");
        myRecyclerViewAdapter.add(0, "LinearLayoutManager");
        myRecyclerViewAdapter.add(0, "RecyclerViewAdapter");
        myRecyclerViewAdapter.add(0, "RecyclerView example");
        myRecyclerViewAdapter.add(0, "RecyclerView");
        myRecyclerViewAdapter.add(0, "android-er.blogspot.com");
        myRecyclerViewAdapter.add(0, "android-er");
        myRecyclerViewAdapter.add(0, "android");

    }

    private RadioGroup.OnCheckedChangeListener optLayoutCheckedChangeListener =
            new RadioGroup.OnCheckedChangeListener(){
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId) {
                    if(optLinearLayoutVertical.isChecked()){
                        myRecyclerView.setLayoutManager(linearLayoutManagerVertical);
                    }else if(optLinearLayoutHorizontal.isChecked()){
                        myRecyclerView.setLayoutManager(linearLayoutManagerHorizontal);
                    }else if(optGridLayoutHorizontal.isChecked()){
                        myRecyclerView.setLayoutManager(gridLayoutManagerHorizontal);
                    }else if(optGridLayoutVertical.isChecked()){
                        myRecyclerView.setLayoutManager(gridLayoutManagerVertical);
                    }
                }
            };


    @Override
    public void onItemClick(RecyclerViewAdapter.ItemHolder item, int position) {
        Toast.makeText(this,
                "Remove " + position + " : " + item.getItemName(),
                Toast.LENGTH_SHORT).show();
        myRecyclerViewAdapter.remove(position);
    }
}



download filesDownload the files (Android Studio Format).

Next:
onDraw() and onDrawOver() of ItemDecoration for RecyclerView

- More step-by-step examples of RecyclerView.

Thursday, July 16, 2015

LinearLayoutManager and GridLayoutManager for RecyclerView

This example show how easy to apply LinearLayoutManager and GridLayoutManager on RecyclerView to make it look like a ListView or GridView.


LinearLayoutManager provides similar functionality to ListView.
GridLayoutManager implementations that lays out items in a grid.


Work on last exercise of "Implement custom ItemDecoration for RecyclerView".

Modify layout/activity_main.xml to add RadioButtons for user to select LayoutManager.
<LinearLayout 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"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <EditText
            android:id="@+id/namefield"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/addbutton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Add"/>

        <RadioGroup
            android:id="@+id/optGroupLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
            <RadioButton
                android:id="@+id/optLinearLayoutVertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="LinearLayout Vertical"
                android:checked="true" />
            <RadioButton
                android:id="@+id/optLinearLayoutHorizontal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="LinearLayout Horizontal" />
            <RadioButton
                android:id="@+id/optGridLayoutVertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="GridLayout Vertical" />
            <RadioButton
                android:id="@+id/optGridLayoutHorizontal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="GridLayout Horizontal" />
        </RadioGroup>
    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/myrecyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>


Modify com.example.androidrecyclerview.MainActivity to implement various LayoutManager.
package com.example.androidrecyclerview;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity implements RecyclerViewAdapter.OnItemClickListener{

    private RecyclerView myRecyclerView;
    private RecyclerViewAdapter myRecyclerViewAdapter;

    EditText nameField;
    Button btnAdd;

    RadioGroup optGroupLayout;
    RadioButton optLinearLayoutHorizontal;
    RadioButton optLinearLayoutVertical;
    RadioButton optGridLayoutHorizontal;
    RadioButton optGridLayoutVertical;

    private LinearLayoutManager linearLayoutManagerVertical;
    private LinearLayoutManager linearLayoutManagerHorizontal;
    private GridLayoutManager gridLayoutManagerVertical;
    private GridLayoutManager gridLayoutManagerHorizontal;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myRecyclerView = (RecyclerView)findViewById(R.id.myrecyclerview);

        linearLayoutManagerVertical =
                new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        linearLayoutManagerHorizontal =
                new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        gridLayoutManagerVertical =
                new GridLayoutManager(this,
                        2, //The number of Columns in the grid
                        LinearLayoutManager.VERTICAL,
                        false);
        gridLayoutManagerHorizontal =
                new GridLayoutManager(this,
                        3, //The number of rows in the grid
                        LinearLayoutManager.HORIZONTAL,
                        false);

        myRecyclerViewAdapter = new RecyclerViewAdapter(this);
        myRecyclerViewAdapter.setOnItemClickListener(this);
        myRecyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerView.setLayoutManager(linearLayoutManagerVertical);

        //Add MyItemDecoration
        myRecyclerView.addItemDecoration(new MyItemDecoration());

        nameField = (EditText)findViewById(R.id.namefield);
        btnAdd = (Button)findViewById(R.id.addbutton);
        btnAdd.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String newName = nameField.getText().toString();

                if(!newName.equals("")){
                    if(myRecyclerViewAdapter.getItemCount()>1){
                        myRecyclerViewAdapter.add(1, newName);
                    }else{
                        myRecyclerViewAdapter.add(0, newName);
                    }
                }
            }
        });

        optGroupLayout = (RadioGroup)findViewById(R.id.optGroupLayout);
        optLinearLayoutHorizontal = (RadioButton)findViewById(R.id.optLinearLayoutHorizontal);
        optLinearLayoutVertical = (RadioButton)findViewById(R.id.optLinearLayoutVertical);
        optGridLayoutHorizontal = (RadioButton)findViewById(R.id.optGridLayoutHorizontal);
        optGridLayoutVertical = (RadioButton)findViewById(R.id.optGridLayoutVertical);
        optGroupLayout.setOnCheckedChangeListener(optLayoutCheckedChangeListener);
    }

    private RadioGroup.OnCheckedChangeListener optLayoutCheckedChangeListener =
            new RadioGroup.OnCheckedChangeListener(){
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId) {
                    if(optLinearLayoutVertical.isChecked()){
                        myRecyclerView.setLayoutManager(linearLayoutManagerVertical);
                    }else if(optLinearLayoutHorizontal.isChecked()){
                        myRecyclerView.setLayoutManager(linearLayoutManagerHorizontal);
                    }else if(optGridLayoutHorizontal.isChecked()){
                        myRecyclerView.setLayoutManager(gridLayoutManagerHorizontal);
                    }else if(optGridLayoutVertical.isChecked()){
                        myRecyclerView.setLayoutManager(gridLayoutManagerVertical);
                    }
                }
            };


    @Override
    public void onItemClick(RecyclerViewAdapter.ItemHolder item, int position) {
        Toast.makeText(this,
                "Remove " + position + " : " + item.getItemName(),
                Toast.LENGTH_SHORT).show();
        myRecyclerViewAdapter.remove(position);
    }
}


Other files, refer to last exercise of "Implement custom ItemDecoration for RecyclerView".

download filesDownload the files (Android Studio Format).

Next:
set SpanSizeLookup to GridLayoutManager of RecyclerView

- More step-by-step examples of RecyclerView.