RecyclerView
can do
horizontal list
grid list
staggered frid layout
morever,we can customed the animation
let’s see how a list view use:
recycle view use in this way:
the view holder in list view is optional,but in recycle is must!!!
we can set a view holder onclick listener,not se the onclick listener for the Recycle,the view holder can access the adapter position that has beenclicked.
how to patice it?
Exercise:
start from
replace list view by recycle view
step:
some basic information:http://developer.android.com/intl/zh-tw/training/material/lists-cards.html
step2:add the library
compile 'com.android.support:recyclerview-v7:23.0.+'
how to use recycle to replace the list view?
- use android.support.v7.widget.RecyclerView to replace listview in the layout xml
- in the program,change the ListView to android.support.v7.widget.RecyclerView
- than you will fins that some method can not use,like setOnItemClickListener or setEmptyView
- create a linear layout manager for the recycle view
LinearLayoutManager mLayoutManager mLayoutManager = new LinearLayoutManager(getContext());
5.create a Forecast Adapter
how?????
create a class that extends RecyclerView.Adapter<MyAdapter.ViewHolder>
craet a VieHolder in the Adapter calss
example:
public class ViewHolder extends RecyclerView.ViewHolder {
public final ImageView mIconView;
public final TextView mDateView;
public final TextView mDescriptionView;
public final TextView mHighTempView;
public final TextView mLowTempView;
public ViewHolder(View view) {
super(view);
mIconView = (ImageView) view.findViewById(R.id.list_item_icon);
mDateView = (TextView) view.findViewById(R.id.list_item_date_textview);
mDescriptionView = (TextView) view.findViewById(R.id.list_item_forecast_textview);
mHighTempView = (TextView) view.findViewById(R.id.list_item_high_textview);
mLowTempView = (TextView) view.findViewById(R.id.list_item_low_textview);
}
}
it should hold all the view that in the listview iteam view.
the super(view) is must
overidemethod:
1.onCreateViewHolder
use to crate the view that will show in a list iteam,and return a view holder that hold the view
example:
public ForecastAdapterforRecycelview.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layoutId = -1;
switch (viewType) {
case VIEW_TYPE_TODAY: {
layoutId = R.layout.list_item_forecast_today;
break;
}
case VIEW_TYPE_FUTURE_DAY: {
layoutId = R.layout.list_item_forecast;
break;
}
}
View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
ViewHolder vh = new ViewHolder(view);
return vh;
}
2.getItemViewType
OPtional,can use to show different view in a same recycle view,accroading the position ,return different int
public int getItemViewType(int position) {
return (position == 0) ? VIEW_TYPE_TODAY : VIEW_TYPE_FUTURE_DAY;
}
3.onBindViewHolder
bind the data to the view
public void onBindViewHolder(ForecastAdapterforRecycelview.ViewHolder holder, int position) {
mCursor.moveToPosition(position);
int weatherId = mCursor.getInt(ForecastFragment.COL_WEATHER_CONDITION_ID);
int defaultImage;
switch (getItemViewType(mCursor.getPosition())) {
case VIEW_TYPE_TODAY:
defaultImage = Utility.getArtResourceForWeatherCondition(weatherId);
break;
default:
defaultImage = Utility.getIconResourceForWeatherCondition(weatherId);
}
if (Utility.usingLocalGraphics(mContext)) {
holder.mIconView.
setImageResource(defaultImage);
} else {
Glide.with(mContext)
.load(Utility.getArtUrlForWeatherCondition(mContext, weatherId))
.error(defaultImage)
.crossFade()
.into(holder.mIconView);
}
// Read date from cursor
long dateInMillis = mCursor.getLong(ForecastFragment.COL_WEATHER_DATE);
// Find TextView and set formatted date on it
holder.mDateView.setText(Utility.getFriendlyDayString(mContext, dateInMillis));
// Read weather forecast from cursor
String description = Utility.getStringForWeatherCondition(mContext, weatherId);
// Find TextView and set weather forecast on it
holder.mDescriptionView.setText(description);
holder.mDescriptionView.setContentDescription(mContext.getString(R.string.a11y_forecast, description));
// For accessibility, we don't want a content description for the icon field
// because the information is repeated in the description view and the icon
// is not individually selectable
// Read high temperature from cursor
double high = mCursor.getDouble(ForecastFragment.COL_WEATHER_MAX_TEMP);
String highString = Utility.formatTemperature(mContext, high);
holder.mHighTempView.setText(highString);
holder.mHighTempView.setContentDescription(mContext.getString(R.string.a11y_high_temp, highString));
// Read low temperature from cursor
double low = mCursor.getDouble(ForecastFragment.COL_WEATHER_MIN_TEMP);
String lowString = Utility.formatTemperature(mContext, low);
holder.mLowTempView.setText(lowString);
holder.mLowTempView.setContentDescription(mContext.getString(R.string.a11y_low_temp, lowString));
}
4.getItemCount
return how many data in a cursor or array,depend what you input to be the source or the array adapter
now, we can use the recycle view
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
important *****
the setLayoutManager is must,if not set,the recycle view will not show anything.
next we will talk about the handle click of the Recycle view
Add back the onClickListerner
package pom2.poly.com.userecyclerviewnotlistview;
/**
* Created by User on 26/1/2016.
*/
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.DataObjectHolder> {
private static String LOG_TAG = "MyRecyclerViewAdapter";
private static MyClickListener myClickListener;
private ArrayList<DataObject> mDataset;
//create a constructor to receive the DataSet
public MyRecyclerViewAdapter(ArrayList<DataObject> myDataset) {
mDataset = myDataset;
}
//TODO:why have a interface MyClickListener here?
public interface MyClickListener {
public void onItemClick(int position, View v);
}
//TODO :why have on ClickListener?
public void setOnItemClickListener(MyClickListener myClickListener) {
this.myClickListener = myClickListener;
}
//Because the View Holder is in the Asapter for Reycle view, we need
// to to create our own ViewHolder first ,the view holder hold all the view in a
// Iteam of the Recycle View,we define what will show in each Iteam of the Recycle view by the XML,
// recycleriew_iteam.xml,in that,it has two TextView
//TODO:why implement View.OnClickListener and overview onClick.Becuase the Recycle view do't have a onClickListerner,so we need to set the onItemClicl to each view first,than use the interface MyClickListener to allow define the what will do after click the view.
// TODO The setOnItemClickListener is a method to accept the myClickListener object
public static class DataObjectHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView label;
TextView dateTime;
public DataObjectHolder(View itemView) {
super(itemView);
label = (TextView) itemView.findViewById(R.id.textView);
dateTime = (TextView) itemView.findViewById(R.id.textView2);
Log.i(LOG_TAG, "Adding Listener");
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
myClickListener.onItemClick(getPosition(), v);
}
}
//here will return the ViewHolder we create,so we need to inflate the XML to view that we decide what will show in each view
@Override
public DataObjectHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_item, parent, false);
DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
return dataObjectHolder;
}
//bind the data to the view,view get from the view holder
@Override
public void onBindViewHolder(DataObjectHolder holder, int position) {
holder.label.setText(mDataset.get(position).getmText1());
holder.dateTime.setText(mDataset.get(position).getmText2());
}
//add iteam to the Dataset,and notify change to the adtapter.
public void addItem(DataObject dataObj, int index) {
mDataset.add(dataObj);
notifyItemInserted(index);
}
public void deleteItem(int index) {
mDataset.remove(index);
notifyItemRemoved(index);
}
//how many iteam,should be the same with the nuber of the Data set size
@Override
public int getItemCount() {
return mDataset.size();
}
Add back the empty view
for a list view,the mListView.setEmptyView(emptyView) can make the list view show the speficicef view when the list view is empty.
But Recycle view don’t have tis feacture.
private View empty;
public View getEmpty() {
return empty;
}
public void setEmpty(View empty) {
this.empty = empty;
}
public void swapCursor(Cursor mCursor) {
this.mCursor = mCursor;
if (mCursor.getCount() == 0) {
empty.setVisibility(View.VISIBLE);
} else {
empty.setVisibility(View.GONE);
notifyDataSetChanged();
}
}
the concept is when the cursor is empty,set the empty view is VISIBLE.if tge cursor is not empty,set it gone.