文章首发:Android程序员日记javascript
做者:贤榆的鱼java
测试阅读时间:8minandroid
有有很长一段时间没有更新了,此次给你们带来了一个框架Demo——仿掘金App,但愿能够经过这个Demo和你们分享一些控件的实际使用!此次呢先给你们带来了自动隐藏布局且带下拉加载更多的listView!你们能够先看看掘金app的效果图,后面咱们把本身的放上来比较一下。
今天先放静态的,明天放一张动的!git
经过仿掘金框架的这个listView你们能够练习到一下几个方面:程序员
[1] listView的基本用法github
[2] listView的viewHolder的复用优化及多条目微信
[3] listview添加headerView实现一些布局和功能app
[4] listview经过footerview和滚动监听实现上拉加载更多框架
[5] listview经过触摸监听事件实现上下bar的布局隐藏功能异步
首先在xml文件中配置listview
<ListView android:scrollbars="none" android:id="@+id/listView" android:fadingEdge="vertical" android:overScrollMode="never" android:dividerHeight="0.5dp" android:divider="#05999999" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" />
上面用到的属性:
android:overScrollMode="never" ——滚动越界的模式:ifcontentscroll和always才会有越界效果!
android:dividerHeight="0.5dp" —— listview item之间间隔的高度
android:divider="#05999999" —— listview item之间间隔的背景或者颜色
android:fadingEdge="vertical" —— 上边和下边有黑色的阴影 值为none的话就没有阴影
android:scrollbars="none" —— 值为horizontal|vertical的时候,会自动隐藏和显示相应的滚动条,值为none时隐藏滚动条。
部分经常使用属性补充:
android:cacheColorHint="#00000000" —— 设置拖动背景色为透明
android:fastScrollEnabled="true" —— 快速滚动效果属性配置,在快速滚动的时候旁边会出现一个小方块的快速滚动效果,自动隐藏和显示,
android:scrollbarTrackVertical="@color/colorAccent" —— 设置滚动条的背景色,只能设置引用不能直接填写“#ffffff”
android:scrollbarThumbVertical="@color/colorPrimaryDark" —— 设置滚动条游标的背景色,这里只能引用不能直接填写“#ffffff”
android:scrollbarStyle="outsideInset" —— 四个值的含义以下
outsideInset : 该ScrollBar显示在视图(view)的边缘,增长了view的padding. 若是可能的话,该ScrollBar仅仅覆盖这个view的背景.
outsideOverlay : 该ScrollBar显示在视图(view)的边缘,不增长view的padding,该ScrollBar将被半透明覆盖
insideInset :该ScrollBar显示在padding区域里面,增长了控件的padding区域,该ScrollBar不会和视图的内容重叠.
insideOverlay : 该ScrollBar显示在内容区域里面,不会增长了控件的padding区域,该ScrollBar以半透明的样式覆盖在视图(view)的内容上.
android:footerDividersEnabled —— 当设为false时,ListView将不会在各个footer之间绘制divider.默认为true。
android:headerDividersEnabled —— 当设为false时,ListView将不会在各个header之间绘制divider.默认为true。
在activity中初始化listview并给他设置adapter
mlistView = (ListView) findViewById(R.id.listView); mAdapter = new ViewHolderAdapter(this, mDates); mlistView.setAdapter(mAdapter);
在adapter当中利用viewholder模式对listView的复用机制进行优化,在滑动的时候会更加的顺畅。以及listview多条目的使用它。经过viewholder内部类以item布局中的控件最为变量,能够有效的避免每次都经过findViewById()来实例化控件,从而达到复用控件实例,优化listview的目的!
而这里用到的多条目通常状况下是为增长listview条目的多样样行,让listview表现的更加丰富!固然还有一个状况就是为了突出数据的结构分层!咱们这里就是为了凸显结构,加了一个文章分类title!
public class ViewHolderAdapter extends BaseAdapter { private final Context mContext; private List<NewsItem> mDates=new ArrayList<>(); private static final int TITLE=0; private static final int CONTENT=1; public ViewHolderAdapter(Context mcontext, List<NewsItem> newsItems) { this.mContext=mcontext; //添加分类的标题 mDates.add(new NewsItem("热门文章")); mDates.addAll(1,newsItems); } @Override public int getItemViewType(int position) { if(position==0){//position为0是itemType为分类Title return TITLE; }else{ return CONTENT; } } //返回listview条目类型的总数,咱们这只有文章和分类title两种! @Override public int getViewTypeCount() { return 2; } //返回listview中的条目数据总数 @Override public int getCount() { return mDates==null?0:mDates.size(); } //返回条目位置对应的内容 @Override public NewsItem getItem(int position) { return mDates.get(position); } @Override public long getItemId(int position) { return position; } //在getView当中对多条目的条目类型进行区分并分别作处理! @Override public View getView(int position, View convertView, ViewGroup parent) { NewsItem item = getItem(position); ContentViewHolder contentViewHolder; TieleViewHolder tieleViewHolder; int type = getItemViewType(position); if(convertView==null){ switch (type){ case TITLE: tieleViewHolder=new TieleViewHolder(); convertView=View.inflate(mContext,R.layout.lv_item_title,null); tieleViewHolder.tv_title= (TextView) convertView.findViewById(R.id.tv_top_title); tieleViewHolder.tv_title.setText(item.getTitle()); //绑定一个viewHolder方便在对convertView复用时也对viewHolder进行复用 convertView.setTag(tieleViewHolder); break; case CONTENT: contentViewHolder=new ContentViewHolder(); convertView=View.inflate(mContext,R.layout.lv_item,null); contentViewHolder.iamge= (ImageView) convertView.findViewById(R.id.iv_image); contentViewHolder.tv_articleInfo= (TextView) convertView.findViewById(R.id.tv_info); contentViewHolder.tv_title= (TextView) convertView.findViewById(R.id.tv_title); contentViewHolder.iamge.setImageResource(item.getImage()); contentViewHolder.tv_title.setText(item.getTitle()); contentViewHolder.tv_articleInfo.setText(item.getArtcileInfo()); convertView.setTag(contentViewHolder); break; } }else{ switch (type){ case TITLE: tieleViewHolder= (TieleViewHolder) convertView.getTag(); tieleViewHolder.tv_title.setText(item.getTitle()); break; case CONTENT: //复用绑定的ViewHolder contentViewHolder= (ContentViewHolder) convertView.getTag(); contentViewHolder.iamge.setImageResource(item.getImage()); contentViewHolder.tv_title.setText(item.getTitle()); contentViewHolder.tv_articleInfo.setText(item.getArtcileInfo()); } } return convertView; } public void addDate(List<NewsItem> newsItems, boolean isHead) { if(mDates==null){ this.mDates =newsItems; }else{ if (isHead){ mDates.addAll(1,newsItems); }else{ mDates.addAll(getCount(),newsItems); } } } //建立两个不一样itemType对应的ViewHolder内部类 public class ContentViewHolder { ImageView iamge; TextView tv_title; TextView tv_articleInfo; } public class TieleViewHolder { TextView tv_title; } }
ListView经过添加HeaderView其实能够实现不少的效果,好比下拉刷新的动画就能够放在HeadView当中。固然此次仿掘金的app用了SwipeRefreshLayout实现了下拉刷新,后面会针对这个写一篇的你们也别急!而这个app中依然也用到了headerView。这里是添加了一个头布局。以下图:
咱们在[ 2 ] 的初始化listview代码以后设置adapter以前加上添加headerView的代码
header = LayoutInflater.from(this).inflate(R.layout.lv_headerview, mlistView, false); //header = getLayoutInflater().inflate(R.layout.lv_headerview,null,true); //header=View.inflate(this,R.layout.lv_headerview,null); mlistView.addHeaderView(header);
注 :
关于lv_headerview.xml的代码你们能够在文末的github地址中获取到,这里就不贴出来了!不过上面代码中也有要注意的地方,我写了三种方式实例化headerView!第一种和第二种是同样!而第三种方法省去了第三个参数!
你们在实例化的时候须要注意的是,若是你的headerview有预留的一段空隙,像个人不居中的同样,那么你的第二个参数须要填写listview的实例对象,而第三个参数须要填写false!不然heaaderview下面的空白就会消失(上面的第2、三个方法就会有该现象)!还有一个就第二个参数填写了listview实例,而第三个对象填写了true!这个时候,就会报错崩溃报以下错误:
Caused by: java.lang.UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView
思路:
Step1:先加载一个带加载标示的footerview
Step2:实现listview的滚动监听事件
Step3:判断是否为最后一个条目?是,就显示footerview而且异步加载数据!加载完毕隐藏footerveiw。
代码实现:
在添加headerview后面添加footerview并实例化footerview里面loading标示
footview = LayoutInflater.from(this).inflate(R.layout.lv_footview, mlistView, false); mLoadMore = (TextView) footview.findViewById(R.id.tv_loadmore); mlistView.addFooterView(footview);
实现listview的滚动监听事件,并在onscroll()方法中完成异步加载数据的操做
mlistView.setOnScrollListener(new AbsListView.OnScrollListener(){ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //使用isLoading布尔值做为标识符避免每次触底时进行屡次加载 if(view.getLastVisiblePosition()==view.getCount()-1&&!isLoading){ mLoadMore.setVisibility(View.VISIBLE); isLoading=true; //new 一个一部任务执行异步任务加载操做! new AsyncTask<Void, Void, List<NewsItem>>() { @Override protected List<NewsItem> doInBackground(Void... params) { SystemClock.sleep(1500); List<NewsItem> loadItems=refreshDate("Old"); return loadItems; } @Override protected void onPostExecute(List<NewsItem> loadItems) { isLoading=false; mLoadMore.setVisibility(View.GONE); mAdapter.addDate(loadItems,false); mAdapter.notifyDataSetChanged(); } }.execute(); } } });
最后咱们来看一下咱们的效果图:
该项目的github地址:https://github.com/luorenyu/JuejinMoudel.git
因为字数的限制,因此整篇不能放在一篇里面!那就先分享前面四个点!第五点就明天继续分享!若是着急的也可先直接去上面的git地址下载源码本身!若是有任何问题,欢迎你们在个人微信公众号【Android程序员日记】里问我!
本篇未完待续,明天继续分享!
喜欢的能够关注个人微信公众号!