編輯:關於Android編程
前言:RecyclerView出現已經有一段時間了,我們肯定不陌生了,可以通過導入support-v7對其進行使用。
根據官方的文檔,該控件用於在有限的窗口中展示大量數據集,其實有了它就可以替代ListView、GridView了。
了解RecyclerView架構,可以高度的解耦,異常的靈活,通過設置它提供的不同LayoutManager,ItemDecoration , ItemAnimator可以實現的想要的效果。
1、首先介紹幾種LayoutManager
LinearLayoutManager mManager = new LinearLayoutManager(mContent); LinearLayoutManager mManager = new LinearLayoutManager(mContent, LinearLayoutManager.VERTICAL, false);//垂直布局,true表示左右翻轉,false不翻轉 GridLayoutManager mManager = new GridLayoutManager(mContent,3); GridLayoutManager mManager = new GridLayoutManager(mContent,3,LinearLayoutManager.HORIZONTAL,false);//每行3列,水平,true表示左右翻轉,false不翻轉 mRecyclerView.setLayoutManager(mManager);
//初始化控件 mRecyclerView = findView(R.id.id_recyclerview); //設置布局管理器 mManager = new LinearLayoutManager(mContent); mRecyclerView.setLayoutManager(mManager); //設置adapter mRecyclerView.setAdapter(mAdapter) //設置Item增加、移除動畫 mRecyclerView.setItemAnimator(new DefaultItemAnimator()); //添加分割線 mRecyclerView.addItemDecoration(new DividerItemDecoration( getActivity(), DividerItemDecoration.HORIZONTAL_LIST));
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_cell,null));
(2)onBindViewHolder:拿到ViewHolder中的控件對其賦值操作
(3)getItemCount():返回數組的size()
public class MyAdapter extends RecyclerView.Adapter { class ViewHolder extends RecyclerView.ViewHolder { TextView tvTitle,tvContent; public ViewHolder(View itemView) { super(itemView); tvTitle = (TextView) itemView.findViewById(R.id.tv_title); tvContent = (TextView) itemView.findViewById(R.id.tv_content); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_cell,null)); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ViewHolder vh = (ViewHolder) holder; CellData cd = data[position]; vh.tvTitle.setText(cd.title); vh.tvContent.setText(cd.content); } @Override public int getItemCount() { return data.length; } private CellData[] data = new CellData[]{new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯")}; }4、效果圖,雖然很難看,但是是基本的實現方式。
可見,RecyclerView和傳統的ListView,GridView使用的流程是一樣的,但是由於RecyclerView的高定制性,使用者越來越多,已經有大部分的開發者放棄使用ListView和GridView了。想要用好RecyclerView也不難,關鍵就在於Adapter的書寫上,接下來介紹一個非常好用的RecyclerView萬能適配器(BaseRecyclerViewAdapterHelper),前幾天接觸到的,感覺十分好用,所包含的功能有以下幾個(官網介紹):
1、添加item點擊、長按事件
mQuickAdapter.setOnRecyclerViewItemClickListener(); mQuickAdapter.setOnRecyclerViewItemLongClickListener();2、新增添加子布局多個控件的點擊事件
protected void convert(BaseViewHolder helper, Status item) { helper.setOnClickListener(R.id.tweetAvatar, new OnItemChildClickListener()) .setOnClickListener(R.id.tweetName, new OnItemChildClickListener()); }Activity
mQuickAdapter.setOnRecyclerViewItemChildClickListener(new BaseQuickAdapter.OnRecyclerViewItemChildClickListener() { @Override public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { String content = null; Status status = (Status) adapter.getItem(position); switch (view.getId()) { case R.id.tweetAvatar: content = "img:" + status.getUserAvatar(); break; case R.id.tweetName: content = "name:" + status.getUserName(); break; } Toast.makeText(AnimationUseActivity.this, content, Toast.LENGTH_LONG).show(); } });3、添加動畫
// 一行代碼搞定(默認為漸顯效果) quickAdapter.openLoadAnimation(); // 默認提供5種方法(漸顯、縮放、從下到上,從左到右、從右到左) quickAdapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN); // 自定義動畫如此輕松 quickAdapter.openLoadAnimation(new BaseAnimation() { @Override public Animator[] getAnimators(View view) { return new Animator[]{ ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1), ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1) }; } });4、添加頭部和尾部
mQuickAdapter.addHeaderView(getView()); mQuickAdapter.addFooterView(getView());5、上拉加載更多
mQuickAdapter.openLoadMore(PAGE_SIZE, true);//必須設置pageSize,否則上拉不會加載,pageSize一般為每次請求需要加載的數據條數 mQuickAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { @Override public void onLoadMoreRequested() { mRecyclerView.post(new Runnable() { @Override public void run() { if (mCurrentCounter >= TOTAL_COUNTER) { mQuickAdapter.notifyDataChangedAfterLoadMore(false); } else { mQuickAdapter.notifyDataChangedAfterLoadMore(DataServer.getSampleData(PAGE_SIZE), true); mCurrentCounter = mQuickAdapter.getItemCount(); } } }); } });可以通過mQuickAdapter.setLoadingView(customView);自定義加載更多的布局
6、使用分組
public class SectionAdapter extends BaseSectionQuickAdapter7、添加多種類型Item{ public SectionAdapter(int layoutResId, int sectionHeadResId, List data) { super(layoutResId, sectionHeadResId, data); } @Override protected void convert(BaseViewHolder helper, MySection item) { helper.setImageUrl(R.id.iv, (String) item.t); } @Override protected void convertHead(BaseViewHolder helper,final MySection item) { helper.setText(R.id.header, item.header); else helper.setOnClickListener(R.id.more, new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context,item.header+"more..",Toast.LENGTH_LONG).show(); } }); }
public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter8、使用setEmptyView{ public MultipleItemQuickAdapter(List data) { super(data); addItemType(MultipleItem.TEXT, R.layout.text_view); addItemType(MultipleItem.IMG, R.layout.image_view); } @Override protected void convert(BaseViewHolder helper, MultipleItem item) { switch (helper.getItemViewType()) { case MultipleItem.TEXT: helper.setImageUrl(R.id.tv, item.getContent()); break; case MultipleItem.IMG: helper.setImageUrl(R.id.iv, item.getContent()); break; } } }
mQuickAdapter.setEmptyView(getView());9、使用拖拽與滑動刪除
OnItemDragListener onItemDragListener = new OnItemDragListener() { @Override public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos){} @Override public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {} @Override public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {} } OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() { @Override public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {} @Override public void clearView(RecyclerView.ViewHolder viewHolder, int pos) {} @Override public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {} }; ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(mAdapter); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback); itemTouchHelper.attachToRecyclerView(mRecyclerView); // 開啟拖拽 mAdapter.enableDragItem(itemTouchHelper, R.id.textView, true); mAdapter.setOnItemDragListener(onItemDragListener); // 開啟滑動刪除 mAdapter.enableSwipeItem(); mAdapter.setOnItemSwipeListener(onItemSwipeListener);
感覺每一個功能都很實用,目前也在努力在項目中進行測試使用。
最常用的莫過於下拉刷新,上拉加載的,基本每個頁面都會用到刷新,需要分頁的頁面還會用到加載。曾經搜了下網上的相關於這方面的資源,感覺基本沒有將RecyclerView配合SwipeRefreshLayout做到很好能刷新和加載的。其他的都是自定義的ListView 和GridView實現的刷新和加載,由於不太想用ListView了,所以就換成了RecyclerView,閒淡少扯,實戰繼續。
先上圖:
需求分析:通過接口返回的數據需要進行分頁
{ "code": 1, "pageCount": 33, "list": [ { "province": "XX省", "city": "XX市", "address": "XX區XX路", "scan_time": "2016/7/9 10:30:44", "product_id": "1", "product_name": "MOOKA4K電視U55H3", "product_small_image": "http://cdn02.ehaier.com/product/561f4f031671c47b688b4851_80_80.jpg", "eancode": "6925876304318", "sn": "DH1TV0A0701HUF530144" } ] }
public class QuickAdapter extends BaseQuickAdapter{ private ImageLoader imageLoader = ImageLoader.getInstance(); public QuickAdapter(List data) { super(data); } public QuickAdapter(int layoutResId, List data) { super(layoutResId, data); } @Override protected void convert(BaseViewHolder helper, ScanRecordRowEntity item) { helper.setText(R.id.tv_product_name, item.getProduct_name()) .setText(R.id.tv_time, item.getScan_time()) .setText(R.id.tv_place, item.getProvince() + item.getCity()); // imageLoader.displayImage(item.getProduct_small_image(), (ImageView) helper.getView(R.id.img_product_logo), ImageLoaderUtils.getDefaultOptions()); Glide.with(mContext) .load(item.getProduct_small_image()) .fitCenter() .placeholder(R.drawable.ic_product_default) .crossFade() .into((ImageView) helper.getView(R.id.img_product_logo)); } }
public class ScanRecordTestActivity extends BaseActivity implements SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { private Listlist = new ArrayList<>(); private String encode; private SwipeRefreshLayout mSwipeRefreshLayout; private RecyclerView mRecyclerView; private QuickAdapter mQuickAdapter; private int pageCount = 1;//分頁返回總頁數 private int page = 1;//當前請求頁為第一頁 private int pageSize = 10;//每次請求10條記錄 @Override protected void initView() { setContentView(R.layout.activity_scan_record_test); setBack(); setTitle("掃描記錄"); mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.id_swiperefresh); RefreshUtil.setSwipeRefreshColor(mSwipeRefreshLayout);//設置刷新框顏色 mRecyclerView = (RecyclerView) findViewById(R.id.id_recycleview); mSwipeRefreshLayout.setOnRefreshListener(this); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); initAdapter(); mRecyclerView.setAdapter(mQuickAdapter); } private void initAdapter() { mQuickAdapter = new QuickAdapter(R.layout.item_scan_record, list); mQuickAdapter.openLoadAnimation(); mRecyclerView.setAdapter(mQuickAdapter); mQuickAdapter.setOnLoadMoreListener(this); mQuickAdapter.setOnRecyclerViewItemClickListener(new BaseQuickAdapter.OnRecyclerViewItemClickListener() { @Override public void onItemClick(View view, int position) { Toasters(Integer.toString(position)); } }); } @Override protected void initData() { encode = getIntent().getStringExtra("encode"); if (NetUtil.isNetConnected(mContext)) { RefreshUtil.setSwipeRefreshLoadingState(mSwipeRefreshLayout);//設置首次加載數據時顯示加載框 getRecord(); } else { Toasters("無網絡連接!"); } } @Override protected void setOnClickEvent() { } private void getRecord() { String url = Constant.GET_SCAN_RECORD + encode + "?rows=" + pageSize + "&page=" + page + "&type"; webHttpconnection.getValue(url, 1); } private void LoadMore(final int page) { String url = Constant.GET_SCAN_RECORD + encode + "?rows=" + pageSize + "&page=" + page + "&type"; webHttpconnection.getValue(url, 2); } @Override public void onRefresh() { page = 1; getRecord(); } @Override public void onLoadMoreRequested() { if (page < pageCount) { page = page + 1; LoadMore(page); } } @Override public void requestJsonOnSucceed(String json, int msgFlag) { super.requestJsonOnSucceed(json, msgFlag); ScanRecordEntity entity; switch (msgFlag) { case 1: RefreshUtil.setSwipeRefreshLoadedState(mSwipeRefreshLayout); entity = JSON.parseObject(json, ScanRecordEntity.class); if (1 == entity.getCode() && null != entity.getList()) { pageCount = entity.getPageCount(); mQuickAdapter.setNewData(entity.getList()); if (pageCount > 1) { mQuickAdapter.openLoadMore(pageSize, true); mQuickAdapter.notifyDataChangedAfterLoadMore(true); } } else { Toasters("無掃描記錄!"); } break; case 2: entity = JSON.parseObject(json, ScanRecordEntity.class); if (1 == entity.getCode() && null != entity.getList()) { mQuickAdapter.addData(entity.getList()); } if (pageCount == page) { mQuickAdapter.notifyDataChangedAfterLoadMore(false); View view = getLayoutInflater().inflate(R.layout.not_loading, (ViewGroup) mRecyclerView.getParent(), false); mQuickAdapter.addFooterView(view); } else { mQuickAdapter.notifyDataChangedAfterLoadMore(true); } break; } } @Override public void requestJsonOnError(int msgFlag) { super.requestJsonOnError(msgFlag); Toasters("網絡不可用"); }
前言:前面我們介紹MediaPlayer相關方法,有人說,沒有實際例子,看得不是很明白,今天在分析MediaPlayer時,順帶一個播放網絡視頻例子。可以自行試試。同樣先
上一篇,我們基本知道了EventBus的使用步驟,接下來先簡單研究一下其中的源碼。在分析源碼之前,我們先回顧一下Java反射的知識點:JAVA反射機制基本定義:JAVA反
ContentProvider為Android四大組件之一,主要用來應用程序之間的數據共享,也就是說一個應用程序用ContentProvider將自己的數據暴露出來,其他
上一篇我們主要了解了為什麼適配,以及怎麼適配,同時給出了部分切圖規范,和在開發過程中需要的一些注意事項,這一遍主要從官方給出的指導建議出發,從視覺的角度來說說怎麼適配。度