<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## (一).前言: 作為Android?L開始,Google更新了新控件RecyclerView和CardView,這兩個控件在之前的文章中已經做了詳細介紹和使用,同時在前面還對下拉刷新組件SwipeRefreshLayout進行相關講解。本來該專題不在更新了,正好昨天有一個群友問到了怎么樣結合SwipeRefreshLayout,RecyclerView,CardView這三種控件實現表格布局界面并且加入下拉刷新和上拉加載更多的效果,那么今天我們來實現并且一步步的完善Demo。 同時關于RecyclerView,CardView,SwipeRefreshLayout控件的使用講解如下: * [RecyclerView完全解析,讓你從此愛上它(二十八)](http://blog.csdn.net/developer_jiangqq/article/details/49927631) * [RecyclerView完全解析之打造新版類Gallery效果(二十九)](http://blog.csdn.net/developer_jiangqq/article/details/49946589) * [RecyclerView完全解析之結合AA(Android Annotations)注入框架實例(三十)](http://blog.csdn.net/developer_jiangqq/article/details/49967587) * [RecyclerView完全解析之下拉刷新與上拉加載SwipeRefreshLayout(三十一)](http://blog.csdn.net/developer_jiangqq/article/details/49992269) * [CardView完全解析與RecyclerView結合使用(三十二)](http://blog.csdn.net/developer_jiangqq/article/details/50000733) 具體代碼已經上傳到下面的項目中,歡迎各位去star和fork一下。 FastDev4Android框架項目地址:[https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android) ##(二).需求介紹 以上三種控件結合需要實現的效果如下: ![](https://box.kancloud.cn/2016-01-18_569c8ec2ddaf3.jpg) 分析需要實現的界面的效果,首先是表格布局(GirdView)的列表,并且加入下拉刷新和上拉加載更多效果。這邊對于表格中每一項我們可以使用CardView,然后列表這塊使用RecyclerView,刷新這塊我們采用Android給我們提供的SwipeRefreshLayout控件,下面我們來具體實現以下這個效果: ##(三).實例實現(基礎): ![](https://box.kancloud.cn/2016-01-18_569c8ec2f2781.jpg) 實現的第一種方法,我們可以把界面中的每一項Item布局都采用CardView來實現,那么每一項最終形成一個表格布局(GirdView),主列表采用RecyclerView,那么這邊的布局管理器需要采用GridLayoutManger并且每行兩列分布即可,通過前面的文章我們知道SwipeRefreshLayout的使用方法在RecyclerView外部套用即可。 3.1.Item?View的布局文件如下: ~~~ <?xmlversion="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cardview="http://schemas.android.com/apk/res-auto" android:id="@+id/instance_cardview" android:layout_width="wrap_content" android:layout_height="wrap_content" cardview:cardBackgroundColor="@color/black" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:background="@color/black" android:gravity="center" android:layout_gravity="center_horizontal" > <ImageView android:layout_margin="3dp" android:id="@+id/item_img" android:layout_width="150dp" android:layout_height="150dp" android:scaleType="fitXY" /> <TextView android:textSize="16sp" android:layout_margin="3dp" android:textColor="@color/white" android:id="@+id/item_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxLines="2" android:lines="2"/> </LinearLayout> </android.support.v7.widget.CardView> ~~~ 該布局主體為一個CardView,在CardView內部為一個圖片和標題TextView組成。 3.2.接著創建繼承自RecyclerView.Adapter的ComInstanceAdapter適配器即可。查看下面的代碼就可以知道,我在里邊自定義兩個ViewHolder,一個專門承載Item View,另一個是承載列表底部Foot?View(用來顯示上拉加載更多提示和進度的)。也就是我們會在布局添加刷新的時候會在RecyclerView的底部多添加一個布局View(Foot View)(該具體使用方法我們在前面的文章已經講過了,如不了解可以查看前文)。并且我們這邊已經也為RecyclerView擴展的Item點擊事件了。唯一和以前實現代碼不一樣的為: ~~~ @Override public int getItemCount() { if(mInstanceBeans.size()%2==0){ //偶數 return mInstanceBeans.size()+1; }else{ return mInstanceBeans.size()+2; } } ~~~ ~~~ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof ItemViewHolder){ if(position<mInstanceBeans.size()){ ((ItemViewHolder)holder).item_img.setImageResource(mInstanceBeans.get(position).getImg()); ((ItemViewHolder)holder).item_tv.setText(mInstanceBeans.get(position).getTitle()); holder.itemView.setTag(position); holder.itemView.setClickable(true); }else { ((ItemViewHolder)holder).item_img.setImageResource(R.drawable.moren); ((ItemViewHolder)holder).item_tv.setText(""); holder.itemView.setClickable(false); } }else if(holder instanceof FootViewHolder){ //上拉加載更多布局數據綁定 } } ~~~ 上面數量我進行判斷需要綁定的數據是偶數還是奇數,因為我們這邊的每一行是兩個數據,如果我們的數據是奇數的話,那么這邊最后的FootView布局會加在右邊了如下顯示: ![](https://box.kancloud.cn/2016-01-18_569c8ec31fbb0.jpg) 這樣的效果是比較丑的,所以要把FootView移動到底部,奇數情況數據進行加1即可,最后數據綁定的時候控制顯示一下。 ComInstanceAdapter完成代碼如下: ~~~ public class ComInstanceAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context mContext; private List<InstanceBean> mInstanceBeans; private LayoutInflater mInflater; //布局新增一項類別 //普通ITEM private static final int ITEM_VIEW=1; //FOOT ITEM private static final int FOOT_VIEW=2; public ComInstanceAdapter(Context context,List<InstanceBean> pInstanceBeans){ this.mContext=context; this.mInstanceBeans=pInstanceBeans; mInflater=LayoutInflater.from(this.mContext); } @Override public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { if (viewType == ITEM_VIEW) { final View view =mInflater.inflate(R.layout.com_instance_item_layout, parent, false); view.setOnClickListener(newView.OnClickListener() { @Override public void onClick(View v) { if (onItemClickListener !=null) { onItemClickListener.onItemClick(view, (int) view.getTag()); } } }); return new ItemViewHolder(view); } else if (viewType == FOOT_VIEW) { View view =mInflater.inflate(R.layout.instance_load_more_layout, parent, false); return new FootViewHolder(view); } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof ItemViewHolder){ if(position<mInstanceBeans.size()){ ((ItemViewHolder)holder).item_img.setImageResource(mInstanceBeans.get(position).getImg()); ((ItemViewHolder)holder).item_tv.setText(mInstanceBeans.get(position).getTitle()); holder.itemView.setTag(position); holder.itemView.setClickable(true); }else { ((ItemViewHolder)holder).item_img.setImageResource(R.drawable.moren); ((ItemViewHolder)holder).item_tv.setText(""); holder.itemView.setClickable(false); } }else if(holder instanceofFootViewHolder){ //上拉加載更多布局數據綁定 } } @Override public int getItemViewType(int position) { if (position + 1 == getItemCount()) { return FOOT_VIEW; } else { return ITEM_VIEW; } } @Override public int getItemCount() { if(mInstanceBeans.size()%2==0){ //偶數 return mInstanceBeans.size()+1; }else{ return mInstanceBeans.size()+2; } } public static class ItemViewHolder extends RecyclerView.ViewHolder{ private ImageView item_img; private TextView item_tv; public ItemViewHolder(View itemView) { super(itemView); item_img=(ImageView)itemView.findViewById(R.id.item_img); item_tv=(TextView)itemView.findViewById(R.id.item_tv); } } /** * 底部FootView布局 */ public static class FootViewHolder extends RecyclerView.ViewHolder{ private TextView foot_view_item_tv; public FootViewHolder(View view) { super(view); foot_view_item_tv=(TextView)view.findViewById(R.id.foot_view_item_tv); } } /** * Item 點擊監聽回調接口 */ public interface OnItemClickListener { void onItemClick(View view,intposition); } private OnItemClickListener onItemClickListener; public OnItemClickListener getOnItemClickListener() { return onItemClickListener; } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener =onItemClickListener; } /** * 進行下拉刷新數據添加 并且刷新UI * @param pInstanceBeans */ public void addRefreshBeans(List<InstanceBean> pInstanceBeans){ List<InstanceBean> temp=new ArrayList<InstanceBean>(); temp.addAll(pInstanceBeans); temp.addAll(mInstanceBeans); mInstanceBeans.removeAll(mInstanceBeans); mInstanceBeans.addAll(temp); notifyDataSetChanged(); } /** * 進行上拉加載更多 并且刷新UI * @param pInstanceBeans */ public void addMoreBeans(List<InstanceBean> pInstanceBeans){ mInstanceBeans.addAll(pInstanceBeans); notifyDataSetChanged(); } } ~~~ 3.3.接下來是布局RecyclerView和SwipeRefreshLayout布局文件了,這個和之前的文章上面的一樣,我們在RecyclerView外部嵌套SwipeRefreshLayout組件即可,最后在Activity中獲取使用。 com_instance_layout.xml布局完整代碼如下: ~~~ <?xmlversion="1.0" encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/black"> <includelayout="@layout/common_top_bar_layout"/> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/instance_swiperefreshlayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scrollbars="none"> <android.support.v7.widget.RecyclerView android:id="@+id/instance_recycler" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scrollbars="none"/> </android.support.v4.widget.SwipeRefreshLayout> </LinearLayout> ~~~ 3.4.最后Activity中初始化SwipeRefreshLayout控件并且設置背景和刷新進度條的顏色。RecyclerView控件初始化以及設置布局管理器(GirdLayoutManger)和適配器即可。 ComInstanceActivity完整代碼如下: ~~~ public class ComInstanceActivity extends BaseActivity { private LinearLayout top_bar_linear_back; private TextView top_bar_title; private RecyclerView instance_recycler; private ComInstanceAdapter adapter; private SwipeRefreshLayout instance_swiperefreshlayout; private int lastVisibleItem; //是否正在加載更多的標志 private boolean isMoreLoading=false; @Override protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.com_instance_layout); top_bar_linear_back=(LinearLayout)this.findViewById(R.id.top_bar_linear_back); instance_swiperefreshlayout=(SwipeRefreshLayout)this.findViewById(R.id.instance_swiperefreshlayout); //設置刷新時動畫的顏色,可以設置4個 instance_swiperefreshlayout.setProgressBackgroundColorSchemeResource(android.R.color.white); instance_swiperefreshlayout.setColorSchemeResources(android.R.color.holo_blue_light, android.R.color.holo_red_light,android.R.color.holo_orange_light, android.R.color.holo_green_light); top_bar_linear_back.setOnClickListener(new CustomOnClickListener()); top_bar_title=(TextView)this.findViewById(R.id.top_bar_title); top_bar_title.setText("綜合實例"); instance_recycler=(RecyclerView)this.findViewById(R.id.instance_recycler); final GridLayoutManager gridLayoutManager=new GridLayoutManager(this,2); instance_recycler.setLayoutManager(gridLayoutManager); instance_recycler.setAdapter(adapter =new ComInstanceAdapter(this, InstanceDataUtils.getInstanceBeans())); //添加Item點擊監聽事件 adapter.setOnItemClickListener(new ComInstanceAdapter.OnItemClickListener() { @Override public void onItemClick(View view,int position) { Toast.makeText(ComInstanceActivity.this,"點擊了第"+position+"項",Toast.LENGTH_SHORT).show(); } }); //下拉刷新 instance_swiperefreshlayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new Handler().postDelayed(newRunnable() { @Override public void run() { List<InstanceBean> temp=new ArrayList<InstanceBean>(); for(inti=0;i<5;i++){ InstanceBean bean=new InstanceBean("我是楊穎Item"+i,R.drawable.baby); temp.add(bean); } adapter.addRefreshBeans(temp); instance_swiperefreshlayout.setRefreshing(false); Toast.makeText(ComInstanceActivity.this, "更新了五條數據...", Toast.LENGTH_SHORT).show(); } },3500); } }); //上拉加載更多 instance_recycler.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState ==RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 ==adapter.getItemCount()) { if(!isMoreLoading){ isMoreLoading=true; newHandler().postDelayed(new Runnable() { @Override public void run() { List<InstanceBean> temp=new ArrayList<InstanceBean>(); for (int i = 0; i< 5; i++) { InstanceBean bean=new InstanceBean("我是MoreItem"+i,R.drawable.meinv); temp.add(bean); } adapter.addMoreBeans(temp); Toast.makeText(ComInstanceActivity.this, "上拉加載了五條數據...", Toast.LENGTH_SHORT).show(); isMoreLoading=false; } },2000); } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView,dx, dy); lastVisibleItem =gridLayoutManager.findLastVisibleItemPosition(); } }); } class CustomOnClickListener implementsView.OnClickListener{ @Override public void onClick(View v) { ComInstanceActivity.this.finish(); } } } ~~~ 上面的代碼中要使用SwipeRefreshLayout實現下拉刷新只要設置OnRefreshListener監聽器即可,要實現上拉加載更多給RecyclerView添加OnScrollListener判斷是否已經下拉滑動的底部,然后開始加載更多數據。 3.5.運行效果如下: ![](https://box.kancloud.cn/2016-01-18_569c8ec3818bb.jpg) ##(四).實例實現(改進版): 看到上面的效果實現,我們會發現一個問題:FootView雖然在底部了,但是表格一行是兩列的,所以FootView就會在底部的最左邊了,只會占據一個CardView的空間。但是我們平時的效果應該是FootView是整一行實現的,這樣比較美觀。OK?下面我們來進行改進一下: 之前RecyclerView我們采用的是GirdLayoutManger布局,這邊我們采用LinearLayoutManger垂直方向實現。這樣的話每一行為單獨的Item了,并且該行Item中我直接放上一個CardView布局,然后在內部添加兩個水平布局的LinearLayout。但是這樣修改之后Item的點擊事件就要進行修改了,我們這邊把點擊事件添加在每一個LinearLayout布局。 4.1.advance_com_instance_item_layout完成布局代碼如下: ~~~ <?xmlversion="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cardview="http://schemas.android.com/apk/res-auto" android:id="@+id/instance_cardview" android:layout_width="fill_parent" android:layout_height="wrap_content" cardview:cardBackgroundColor="@color/black" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="@color/black" android:gravity="center" android:layout_gravity="center_horizontal" > <LinearLayout android:id="@+id/leftL" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_weight="1" android:gravity="center"> <ImageView android:src="@drawable/meinv" android:layout_margin="3dp" android:id="@+id/item_img_one" android:layout_width="150dp" android:layout_height="150dp" android:scaleType="fitXY" /> <TextView android:text="古代美女" android:textSize="16sp" android:layout_margin="3dp" android:textColor="@color/white" android:id="@+id/item_tv_one" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxLines="2" android:lines="2"/> </LinearLayout> <LinearLayout android:id="@+id/rightL" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_weight="1" android:gravity="center"> <ImageView android:src="@drawable/liuyan" android:layout_margin="3dp" android:id="@+id/item_img_two" android:layout_width="150dp" android:layout_height="150dp" android:scaleType="fitXY" /> <TextView android:text="柳巖" android:textSize="16sp" android:layout_margin="3dp" android:textColor="@color/white" android:id="@+id/item_tv_two" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxLines="2" android:lines="2"/> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView> ~~~ 我們看到上面的布局中兩個LinearLayout分別加上了兩個id,用來后面獲取控件并且添加點擊監聽事件。 4.2.然后自定義適配器中的數據綁定方法和之前的有所不同: ~~~ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof ItemViewHolder){ AdvanceInstanceBean advanceInstanceBean=mAdvanceInstanceBeans.get(position); if(advanceInstanceBean!=null){ final List<InstanceBean> instanceBeans=advanceInstanceBean.getInstanceBeans(); if(instanceBeans.size()==2){ ((ItemViewHolder)holder).item_img_one.setImageResource(instanceBeans.get(0).getImg()); ((ItemViewHolder)holder).item_tv_one.setText(instanceBeans.get(0).getTitle()); ((ItemViewHolder)holder).item_img_two.setImageResource(instanceBeans.get(1).getImg()); ((ItemViewHolder)holder).item_tv_two.setText(instanceBeans.get(1).getTitle()); ((ItemViewHolder)holder).leftL.setOnClickListener(new View.OnClickListener() { @Override public voidonClick(View v) { if(onItemClickListener != null) { onItemClickListener.onItemClick(instanceBeans.get(0)); } } }); ((ItemViewHolder)holder).rightL.setOnClickListener(new View.OnClickListener() { @Override public voidonClick(View v) { if(onItemClickListener!=null){ onItemClickListener.onItemClick(instanceBeans.get(1)); } } }); }else { ((ItemViewHolder)holder).item_img_one.setImageResource(instanceBeans.get(0).getImg()); ((ItemViewHolder)holder).item_tv_one.setText(instanceBeans.get(0).getTitle()); ((ItemViewHolder)holder).item_img_two.setImageResource(R.drawable.moren); ((ItemViewHolder)holder).item_tv_two.setText(""); } } }else if(holder instanceof FootViewHolder){ //上拉加載更多布局數據綁定 } } ~~~ 上面的數據綁定代碼中,給左右兩個布局分別加入了onClick事件,來進行回調點擊數據傳遞。具體回調接口定義如下: ~~~ /** * Item 點擊監聽回調接口 */ public interface OnItemClickListener { /** * item回調的數據 * @param instanceBean */ void onItemClick(InstanceBean instanceBean); } ~~~ 具體完成代碼比較多就不貼了,到時候大家clone一下項目代碼: FastDev4Android框架項目地址:[https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android) 4.3.Acitivty中處理初始化設置的代碼就不貼了 4.4.運行效果如下: ![](https://box.kancloud.cn/2016-01-18_569c8ec507414.jpg) ## (五).最后總結 今天我們通過SwipeRefreshLayout+RecyclerView+CardView實現的表格布局以及下拉刷新,上拉加載更多的效果。 本次實例代碼因為比較多,代碼全貼比較浪費篇幅,重點在于講解思路了。不過實例注釋過的全部代碼已經上傳到Github項目中了。同時歡迎大家去Github站點進行clone或者fork瀏覽整個開源快速開發框架項目~ [https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看