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.


3 comments:

Anonymous said...

Hi
------------------------
I want to do app read the text from the WebView or convert WebView page Content to text
using C# Xamarin.Android code
-------------------------
https://drive.google.com/file/d/0B57zljJtEWstVERPOGYyX2Z3d1U/view?usp=sharing

Unknown said...

Thanks for sharing your knowledge with everyone, I wanted to ask how I can place a spinner in a recyclcerview, you have some tutorial or link about this, you appreciate too.

what's up said...

Thank you.
I had some problem and i couldn't find any clues to solve it.
finally, i got clue in your posting.
-the problem was i forgot adding "final"-

Thank you again from Korea! :)