[Android学习笔记三] Support v7提供交错式网格布局开发示例
本文主要介绍Android Support v7提供的RecycleView和交错式布局(通常成为瀑布流布局)的使用和事件监听处理。
1. 涉及到开源库有:
Fresco :
Facebook开源的不是一般强大的图片加载组件库
Bufferknife :
Android View和事件绑定库,通过注解完成,在编译时APT处理注解文档。
2. 模块配置
Android Studio模块,build.gradle配置:
applyplugin:'com.android.application'android{compileSdkVersion21buildToolsVersion'21.1.2'defaultConfig{applicationId'secondriver.sdk'minSdkVersion16targetSdkVersion21versionCode1versionName'1.0'}buildTypes{release{minifyEnabledfalseproguardFilesgetDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'}}packagingOptions{exclude'META-INF/services/javax.annotation.processing.Processor'}lintOptions{disable'InvalidPackage'}}dependencies{compilefileTree(dir:'libs',include:['*.jar'])compile'com.android.support:appcompat-v7:21.0.3'compile'com.android.support:recyclerview-v7:21.0.3@aar'compile'com.android.support:cardview-v7:21.0.3@aar'compile'com.facebook.fresco:fresco:0.8.0'compile'com.jakewharton:butterknife:7.0.1'testCompile'junit:junit:4.12'}
3. 布局文件
主布局文件:activity_recycleview.xml 包含一个RecycleView,将作为主屏幕组件。
<?xmlversion="1.0"encoding="utf-8"?><RelativeLayoutandroid:id="@+id/swipe_refresh_layout"xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.v7.widget.RecyclerViewandroid:id="@+id/recycler_view"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:scrollbars="vertical"/></RelativeLayout>
RecycleView 通过设置不同的布局管理器对象来实现不同的布局显示,如:
android.support.v7.widget.LinearLayoutManager 可以实现ListView的布局效果
android.support.v7.widget.GridLayoutManager 可以实现GridView的布局效果
android.support.v7.widget.StaggeredGridLayoutManager 可以实现交错式网格布局效果
次布局文件(RecycleView中显示的每一项视图的布局):item_recycelview.xml 通过com.android.support:CardView包提供的CardView帧式容器布局包含一个ImageView和TextView作为RecycleView的每一项视图的布局。
<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:card_view="http://schemas.android.com/apk/res-auto"xmlns:fresco="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"><android.support.v7.widget.CardViewandroid:id="@+id/card_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"card_view:cardCornerRadius="4dp"card_view:cardUseCompatPadding="true"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><com.facebook.drawee.view.SimpleDraweeViewandroid:id="@+id/info_p_w_picpath"android:layout_width="300dp"android:layout_height="420dp"fresco:actualImageScaleType="centerCrop"fresco:placeholderImage="@mipmap/ic_launcher"fresco:roundAsCircle="false"fresco:roundBottomLeft="true"fresco:roundBottomRight="true"fresco:roundTopLeft="true"fresco:roundTopRight="true"fresco:roundedCornerRadius="1dp"fresco:roundingBorderWidth="2dp"/><TextViewandroid:id="@+id/info_text"android:layout_width="200dp"android:layout_height="80dp"android:textSize="20sp"android:textColor="@android:color/holo_blue_dark"android:textAppearance="?android:attr/textAppearanceMedium"android:layout_alignLeft="@id/info_p_w_picpath"android:layout_alignRight="@id/info_p_w_picpath"android:layout_below="@id/info_p_w_picpath"android:gravity="left|center_vertical"/></RelativeLayout></android.support.v7.widget.CardView></LinearLayout>
ImageView组件使用的是Fresco库提供的视图组件。
4. Activity实现和数据填充
4.1 RecycleView中的每一项视图的数据组成
文本信息+ 图片地址(url,file,resId) 本示例中采用Url网络图片
/***View项的数据对象*/staticclassPair{publicStringtext;publicStringurl;publicPair(Stringtext,Stringurl){this.text=text;this.url=url;}}
4.2 RecycleView中国的每一项视图的数据填充,即适配器
自定义适配器需要实现RecycleView.Adapter类。
staticclassRecycleViewAdapterextendsRecyclerView.Adapter<RecyclerView.ViewHolder>{/***RecycleView的View项单击事件监听*/publicinterfaceOnRecycleViewItemClickListener{voidonRecycleViewItemClick(Viewview,intposition);}privateArrayList<Pair>items=newArrayList<>();privateOnRecycleViewItemClickListenermOnRecycleViewItemClickListener;publicRecycleViewAdapter(ArrayList<Pair>items){this.items=items;}@OverridepublicRecyclerView.ViewHolderonCreateViewHolder(ViewGroupparent,intviewType){Viewview=LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recyclerview,parent,false);returnnewRecycleViewItemHolder(view,mOnRecycleViewItemClickListener);}@OverridepublicvoidonBindViewHolder(RecyclerView.ViewHolderholder,intposition){Pairpair=items.get(position);((RecycleViewItemHolder)holder).setContent(pair);}@OverridepublicintgetItemCount(){returnitems.size();}publicvoidsetOnRecycleViewItemClickListener(OnRecycleViewItemClickListeneronItemClickListener){if(null!=onItemClickListener){this.mOnRecycleViewItemClickListener=onItemClickListener;}}}
主要实现onCreateViewHolder和onBindViewHolder方法。由于RecycleView并未提供为视图项添加监听事件,这里自定义个一个事件监听接口,在实例化适配器的时候可以选择设置事件监听。
4.3 创建ViewHolder需要通过自定义ViewHolder类继承RecycleView.ViewHolder。
staticclassRecycleViewItemHolderextendsRecyclerView.ViewHolderimplementsView.OnClickListener{@Bind(R.id.info_text)publicTextViewinfoTextView;@Bind(R.id.info_p_w_picpath)publicSimpleDraweeViewdraweeView;privateRecycleViewAdapter.OnRecycleViewItemClickListeneronItemClickListener;publicRecycleViewItemHolder(ViewitemView,RecycleViewAdapter.OnRecycleViewItemClickListeneronItemClickListener){super(itemView);ButterKnife.bind(this,itemView);this.onItemClickListener=onItemClickListener;itemView.setOnClickListener(this);}publicvoidsetContent(Pairpair){infoTextView.setText(pair.text);draweeView.setImageURI(Uri.parse(pair.url));}@OverridepublicvoidonClick(Viewv){if(null!=onItemClickListener){onItemClickListener.onRecycleViewItemClick(v,getPosition());}}}
在构造方法中的传入OnRecycleViewItemClickListener对象,并且自定义ViewHolder实现OnClickListener接口,通过为itemView对象设置OnClickListener监听事件,在onClick方法中将点击事件的处理交由OnRecycleViewItemClickListener对象处理,从而达到为RecycleView中的itemView注册点击事件。
如果不采用这种方式添加事件监听,就不需要自定义监听接口和自定义ViewHolder实现事件监听接口以及事件处理。另外可以通过获得的itemView之后,通过组件I的获取组件来添加事件监听。还可以通过获得的自定义ViewHolder,来访问每个组件。
4.4 Activity的具体实现
packagesecondriver.sdk.activity;importandroid.app.Activity;importandroid.net.Uri;importandroid.os.Bundle;importandroid.support.v7.widget.DefaultItemAnimator;importandroid.support.v7.widget.RecyclerView;importandroid.support.v7.widget.StaggeredGridLayoutManager;importandroid.util.Log;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.TextView;importandroid.widget.Toast;importcom.facebook.drawee.view.SimpleDraweeView;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Random;importbutterknife.Bind;importbutterknife.ButterKnife;importsecondriver.sdk.R;/***Author:secondriver*Created:2015/11/18*/publicclassRecycleViewActivityextendsActivity{privatestaticfinalStringTAG=RecyclerView.class.getName();privatestaticfinalString[]RES_URL=newString[]{"http://p1.wmpic.me/article/2015/11/16/1447644849_hySANEEF.jpg",//减少篇幅,此处省去14个图片Url};@Bind(R.id.recycler_view)publicRecyclerViewmRecycleView;privatefinalintPRE_SCREEN_NUMBER=6;privatefinalintSPAN_COUNT=2;privateintpreviousLastIndex=0;privatebooleanisSlidingToLast=false;privateRecycleViewAdaptermAdapter;privateArrayList<Pair>mItem=newArrayList<>();//交错式网格布局管理对象,即通常称的瀑布流布局privateStaggeredGridLayoutManagermLayoutManager;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_recyclerview);ButterKnife.bind(this);Fresco.initialize(this);//重要,Fresco做一系列初始化工作initRecycleView();}privatevoidinitRecycleView(){mLayoutManager=newStaggeredGridLayoutManager(SPAN_COUNT,StaggeredGridLayoutManager.VERTICAL);mRecycleView.setLayoutManager(mLayoutManager);mAdapter=newRecycleViewAdapter(mItem);loadData(false);mRecycleView.setAdapter(mAdapter);mRecycleView.setItemAnimator(newDefaultItemAnimator());//RecycleView的View项单击事件监听mAdapter.setOnRecycleViewItemClickListener(newRecycleViewAdapter.OnRecycleViewItemClickListener(){@OverridepublicvoidonRecycleViewItemClick(Viewview,intposition){longid=mRecycleView.getChildItemId(view);Log.d(TAG,"View项的根视图:"+view.getClass().getName()+",position="+position+"ViewHolder_Id="+id);//通过findViewById查找View项中的元素SimpleDraweeViewdraweeView=(SimpleDraweeView)view.findViewById(R.id.info_p_w_picpath);if(null!=draweeView){draweeView.setImageURI(Uri.parse(RES_URL[0]));Toast.makeText(RecycleViewActivity.this,"通过findViewById查找View项中的元素",Toast.LENGTH_LONG).show();}RecycleViewItemHolderrecycleViewItemHolder=(RecycleViewItemHolder)mRecycleView.findViewHolderForPosition(position);if(null!=recycleViewItemHolder){recycleViewItemHolder.infoTextView.setText("通过ViewHolder找到View项中的元素");}}});//下拉刷新,追加内容mRecycleView.setOnScrollListener(newRecyclerView.OnScrollListener(){@OverridepublicvoidonScrollStateChanged(RecyclerViewrecyclerView,intnewState){super.onScrollStateChanged(recyclerView,newState);if(newState==RecyclerView.SCROLL_STATE_IDLE){if(isPullToBottom()&&isSlidingToLast){if(mItem.size()>36){//最大数据量Toast.makeText(RecycleViewActivity.this,"没有数据了",Toast.LENGTH_LONG).show();return;}else{loadData(false);Log.d(TAG,"notifyItemRangeInsertedstartPosition="+previousLastIndex);mAdapter.notifyItemRangeInserted(previousLastIndex,PRE_SCREEN_NUMBER);}}}if(newState==RecyclerView.SCROLL_STATE_SETTLING){Log.d(TAG,"settling");}}@OverridepublicvoidonScrolled(RecyclerViewrecyclerView,intdx,intdy){super.onScrolled(recyclerView,dx,dy);isSlidingToLast=dy>0;//上拉,下滑Log.d(TAG,"dx="+dx+"dy="+dy+"isSlidingToLast="+isSlidingToLast);}});}privatebooleanisPullToBottom(){int[]lastIndexs=mLayoutManager.findLastCompletelyVisibleItemPositions(null);Log.d(TAG,"lastitem="+Arrays.toString(lastIndexs)+",haveitem="+mAdapter.getItemCount());intmaxIndex=mAdapter.getItemCount()-1;for(inti:lastIndexs){if(i==maxIndex){returntrue;}}returnfalse;}privatevoidloadData(booleanisClear){if(isClear){mItem.clear();}previousLastIndex=mItem.size();Randomr=newRandom();for(intindex=0;index<PRE_SCREEN_NUMBER&&index<RES_URL.length;index++){mItem.add(newPair("Card"+(previousLastIndex+index),RES_URL[r.nextInt(RES_URL.length)]));}Log.d(TAG,"mItemcount="+mItem.size());}}
说明:
RecycleView的ItemView的数据由Pair对象管理存储
Fresco库默认配置下的使用之前需要初始化调用Fresco.initialize(Context)
上述实现了2个事件监听,一个OnScrollerListener由RecycleView提供,实现下拉刷新;一个OnRecycleViewItemClickListener由自定义的RecycleViewAdpater提供,实现单击itemView来更换图片(SimpleDraweeView)和文字(TextView)。
Butterknife和Fresco库的具体使用参见其Github上的文档。
5. 效果图
比较遗憾ScreenRecord不支持模拟器和Android4.4一下的系统,只能附上截图。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。