Monday, October 5, 2015

How to use View Holder in Android

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    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:background="#fff"
    >
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Generate Gallery"
        />
    <GridView
        android:id="@+id/gv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:horizontalSpacing="2dp"
        android:verticalSpacing="2dp"
        android:padding="2dp"
        android:gravity="center"
        android:background="#dedfdd"
        android:layout_below="@id/btn"
        android:visibility="gone"
        />
</RelativeLayout>
MainActivity.java

package com.cfsuman.me.baseadapterexample;

import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.GridView;
import android.content.Context;
import android.view.WindowManager;
import android.view.Display;
import android.graphics.Point;

public class MainActivity extends AppCompatActivity {
    private Context mContext;
    private int mGridView_Column_Width = 100; // In DPs

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

        mContext = getApplicationContext();

        // Set action bar background color
        getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.RED));

        // Get the widget reference from XML layout
        final GridView gv = (GridView) findViewById(R.id.gv);
        Button btn = (Button) findViewById(R.id.btn);

        // Set GridView number of columns
        setGridViewNumberOfColumns(gv);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Initialize a new instance of BaseAdapter
                MyBaseAdapter adapter = new MyBaseAdapter(mContext);

                // Data bind the GridView with BaseAdapter
                gv.setAdapter(adapter);

                // Visible the GridView
                gv.setVisibility(View.VISIBLE);
            }
        });
    }

    // Set the GridView number of columns
    private void setGridViewNumberOfColumns(GridView gv){
        int numberOfColumns = Math.round(getScreenWidthInDPs()/mGridView_Column_Width);
        if(numberOfColumns<=2){
            gv.setNumColumns(GridView.AUTO_FIT);
        }
        else{
            gv.setNumColumns(numberOfColumns);
        }
    }

    // Custom method to get the screen width in dp
    private int getScreenWidthInDPs(){
        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        //Display dimensions in pixels
        display.getSize(size);
        int width = size.x;
        //int height = size.y;
        return getDPsFromPixels(width);
    }

    // Method for converting pixels value to dp
    private int getDPsFromPixels(int pixels){
        Resources r = mContext.getResources();
        int  dps = Math.round(pixels/(r.getDisplayMetrics().densityDpi/160f));
        return dps;
    }
}
viewholder_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="2dp"
    android:background="#ffffff"
    >
    <ProgressBar
        android:id="@+id/pb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        style="?android:attr/progressBarStyleSmall"
        />
    <ImageView
        android:id="@+id/iv"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:scaleType="fitCenter"
        android:visibility="invisible"
        />
    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/iv"
        android:textSize="8dp"
        android:textColor="#000000"
        android:layout_centerHorizontal="true"
        android:fontFamily="sans-serif-condensed"
        android:visibility="invisible"
        />
</RelativeLayout>
MyBaseAdapter.java

package com.cfsuman.me.baseadapterexample;

import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.BaseAdapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.graphics.Bitmap;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.os.AsyncTask;
import android.view.LayoutInflater;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;


public class MyBaseAdapter extends BaseAdapter {
    private Context mContext;
    private String mImageFolderName = "animals";
    private String[] mImageNameArray = new String[]{};

    MyBaseAdapter(Context context){
        mContext = context;
    }

    @Override
    public int getCount(){
        return getImageNames().length;
    }

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

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent){
        ViewHolder holder;
        if(convertView == null)
        {
            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.viewholder_layout,null);
            holder = new ViewHolder();
            holder.pb = (ProgressBar) convertView.findViewById(R.id.pb);
            holder.tv = (TextView) convertView.findViewById(R.id.tv);
            holder.iv = (ImageView) convertView.findViewById(R.id.iv);
            holder.pos = position;

            // Get the current image name
            final String currentImageName = getImageNames()[position];
            // Current image file path
            final String currentImagePath = mImageFolderName+"/"+currentImageName;

            new AsyncTask<ViewHolder, Void, Bitmap>() {
                private ViewHolder v;

                @Override
                protected Bitmap doInBackground(ViewHolder... params) {
                    v = params[0];
                    Bitmap bitmap=null;
                    try{
                        InputStream is;
                        is = mContext.getAssets().open(currentImagePath);
                        bitmap = BitmapFactory.decodeStream(is);
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                    return bitmap;
                }

                @Override
                protected void onPostExecute(Bitmap result) {
                    super.onPostExecute(result);
                    if (v.pos == position) {
                        v.pb.setVisibility(View.GONE);
                        v.tv.setText(formatImageName(currentImageName));
                        v.tv.setVisibility(View.VISIBLE);
                        v.iv.setImageBitmap(result);
                        v.iv.setVisibility(View.VISIBLE);
                        Log.d("AsyncTask",currentImagePath);
                    }
                }
            }.execute(holder);

            // Set a click listener for ImageView
            holder.iv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // Do something
                }
            });
            convertView.setTag(holder);
        }
        else
        {
            // Do something
        }
        return convertView;
    }

    // Get the current image name without extension
    private String formatImageName(String imageName){
        int endingIndex = imageName.indexOf('.');
        if(endingIndex>=0){
            imageName = imageName.substring(0,endingIndex);
        }
        return imageName;
    }

    // Get the image list from asset sub folder as random order
    public String[] getImageNames(){
        if(mImageNameArray.length<1){
            try{
                mImageNameArray = mContext.getAssets().list(mImageFolderName);
                // Randomize the array elements
                Collections.shuffle(Arrays.asList(mImageNameArray));

                // Log, how many times actually sent query to asset folder
                //Log.d("Query image name: ", "");
            }catch (IOException e)
            {
                e.printStackTrace();
            }

            for(int i=0;i<mImageNameArray.length;i++){
                // Log, images of asset sub folder
                //Log.d("Image", i+1 +" of "+ mImageNameArray.length+" : " + mImageNameArray[i]);
            }
        }

        // Log, when getImageNames() method call
        //Log.d("getImages()", "");

        return mImageNameArray;
    }

    static class ViewHolder{
        ProgressBar pb;
        TextView tv;
        ImageView iv;
        int pos;
    }
}
More android examples