視圖組
視圖組參數(shù)
可定制項
xml文件
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
ViewHolder
簡介
-
ViewHolder
有個itemView
私有成員,可以從itemView
中通過findViewById()
找到子View
雨女。
- 保留
context
注意內(nèi)存泄漏問題谚攒,可以使用Application
的Context
。
- 此處
context
非必要氛堕。
簡單示例
@SuppressWarnings({"FieldCanBeLocal", "unused"})
class Holder extends RecyclerView.ViewHolder {
private Context mContext;
// Todo: View成員
// Todo: Model成員
Holder(Context context, View itemView) {
super(itemView);
bindView(itemView);
mContext = context;
}
void bindModel(/* Model */) {
// Todo: 初始化Model
// Todo: 綁定View和Model
}
void setOnClickListener(View.OnClickListener onClickListener) {
itemView.setOnClickListener(onClickListener);
}
private void bindView(View itemView) {
// Todo: 初始化View
}
}
Adapter
簡介
- 保留
context
注意內(nèi)存泄漏問題馏臭,可以使用Application
的Context
。
- 此處
context
非必要讼稚。
簡單示例
public class Adapter extends RecyclerView.Adapter<Holder> {
private Context mContext;
// Todo: Models
// Todo: 構(gòu)造
public Adapter(Context context, /* Models */) {
mContext = context;
// 初始化Models
}
@Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
// Todo: 載入布局
View view = layoutInflater.inflate(/*View Layout Id*/, parent, false);
return new Holder(mContext, view);
}
@Override
public void onBindViewHolder(Holder holder, int position) {
// Todo: Get Model in Models by Position
// Todo: Bind Model and Holder
}
@Override
public int getItemCount() {
// Todo: return Size
return /* Size */;
}
}
LayoutManager
LinearLayoutManager
RecyclerView mRecyclerView = /* 初始化 */;
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
GridLayoutManager
RecyclerView mRecyclerView = /* 初始化 */;
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2, GridLayoutManager.VERTICAL, false));
StaggeredGridLayoutManager
RecyclerView mRecyclerView = /* 初始化 */;
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
ItemDecoration
簡介
- 用于定制繪制子項行為
- 繪制順序:
onDraw()
-> 子項 ->onDrawOver()
簡單示例
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:height="2dp"/>
<solid android:color="#8b2cab"/>
</shape>
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public DividerItemDecoration(Context context) {
mDivider = context.getResources().getDrawable(R.drawable.d, null);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount - 1; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
// 設(shè)置mDivider的繪畫區(qū)域和寬高括儒,相當于給定左上角和右下角坐標確定一個矩形
mDivider.setBounds(left, top, right, bottom);
// 在畫布(Canvas)上畫
mDivider.draw(c);
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
// Item偏移
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getAdapter().getItemCount() - 1 == parent.getChildAdapterPosition(view))
outRect.set(0, 0, 0, 0);
else {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
}
}
}
ItemAnimator
- 用于定制子項動畫增刪。
- 通過復制粘貼
DefaultItemAnimator
并重寫其中的幾個函數(shù)來控制動畫
animateRemoveImpl
animateAddImpl
animateMoveImpl
animateChangeImpl
-
endAnimation
:恢復原狀
-
endAnimations
:恢復原狀
- 因為復用的原因乱灵,子項動畫處理完畢后必須恢復原狀塑崖。
- 【Todo】:可以封裝
RecyclerView
RecyclerView mRecyclerView = /* 初始化 */;
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
Adapter adapter = new Adapter(getActivity(), /* Models */);
mRecyclerView.setAdapter(adapter);
顯示沒有內(nèi)容
注意事項
- 對于因為復用導致索引錯亂的問題,使用
ViewHolder.getAdapterPosition()
解決澜躺。若找不到ViewHolder
蝉稳,會返回-1
,注意處理這種情況掘鄙。
- 項目發(fā)生改變時( 增加 耘戚、 刪除 、 修改 )操漠,記得調(diào)用
notify()
系列函數(shù)收津。
ViewPager
xml文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
FragmentStatePagerAdapter
FragmentManager fragmentManager = getSupportFragmentManager();
mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
@Override
public Fragment getItem(int position) {
return /* fragment */;
}
// 獲取當前的顯示的那一頁的Fragment
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
mPageFragment = (PageFragment) object;
}
@Override
public int getCount() {
return /* size */;
}
});
FragmentPagerAdapter
- 相對比于
FragmentStatePagerAdapter
,FragmentPagerAdapter
不會回收復用浊伙。
- 使用方法參見
FragmentStatePagerAdapter
撞秋。
PagerAdapter
@SuppressWarnings("WeakerAccess")
public class CustomPagerAdapter extends PagerAdapter {
private Context mContext;
public CustomPagerAdapter(Context context) {
mContext = context;
}
@Override
public Object instantiateItem(ViewGroup collection, int position) {
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(/* Layout */, collection, false);
collection.addView(layout);
return layout;
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
@Override
public int getCount() {
return /* size */;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
常用方法
-
setCurrentItem()
:設(shè)置當前頁數(shù)。
-
setOffscreenPageLimit()
:預加載頁數(shù)嚣鄙。