Android RecyclerView 使用完全解析 体验艺术般的控件

概述 RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。 据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。 那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。 你想要控制其显示的方式,请通过布局管理器LayoutManager 你想要控制Item间的间隔(可绘制),请通过ItemDecoration 你想要控制Item增删的动画,请通过ItemAnimator 你想要控制点击、长按事件,请自己写(擦,这点尼玛。) 基本使用 鉴于我们对于ListView的使用特别的熟悉,对比下RecyclerView的使用代码: `mRecyclerView = findView(R.id.id_recyclerview); <span class="hljs-comment">//设置布局管理器</span> mRecyclerView.setLayoutManager(layout); <span class="hljs-comment">//设置adapter</span> mRecyclerView.setAdapter(adapter) <span class="hljs-comment">//设置Item增加、移除动画</span> mRecyclerView.setItemAnimator(<span class="hljs-keyword">new</span> DefaultItemAnimator()); <span class="hljs-comment">//添加分割线</span> mRecyclerView.addItemDecoration(<span class="hljs-keyword">new</span> DividerItemDecoration( getActivity(), DividerItemDecoration.HORIZONTAL_LIST));` ok,相比较于ListView的代码,ListView可能只需要去设置一个adapter就能正常使用了。而RecyclerView基本需要上面一系列的步骤,那么为什么会添加这么多的步骤呢? 那么就必须解释下RecyclerView的这个名字了,从它类名上看,RecyclerView代表的意义是,我只管Recycler View,也就是说RecyclerView只管回收与复用View,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现ListView,GirdView,瀑布流等效果)。 Just like ListView Activity `<span class="hljs-keyword">package</span> com.zhy.sample.demo_recyclerview; <span class="hljs-keyword">import</span> java.util.ArrayList; <span class="hljs-keyword">import</span> java.util.List; <span class="hljs-keyword">import</span> android.os.Bundle; <span class="hljs-keyword">import</span> android.support.v7.app.ActionBarActivity; <span class="hljs-keyword">import</span> android.support.v7.widget.LinearLayoutManager; <span class="hljs-keyword">import</span> android.support.v7.widget.RecyclerView; <span class="hljs-keyword">import</span> android.support.v7.widget.RecyclerView.ViewHolder; <span class="hljs-keyword">import</span> android.view.LayoutInflater; <span class="hljs-keyword">import</span> android.view.View; <span class="hljs-keyword">import</span> android.view.ViewGroup; <span class="hljs-keyword">import</span> android.widget.TextView; <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomeActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ActionBarActivity</span> {</span> <span class="hljs-keyword">private</span> RecyclerView mRecyclerView; <span class="hljs-keyword">private</span> List<String> mDatas; <span class="hljs-keyword">private</span> HomeAdapter mAdapter; <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) { <span class="hljs-keyword">super</span>.onCreate(savedInstanceState); setContentView(R.layout.activity_single_recyclerview); initData(); mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); mRecyclerView.setLayoutManager(<span class="hljs-keyword">new</span> LinearLayoutManager(<span class="hljs-keyword">this</span>)); mRecyclerView.setAdapter(mAdapter = <span class="hljs-keyword">new</span> HomeAdapter()); } <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initData</span>() { mDatas = <span class="hljs-keyword">new</span> ArrayList<String>(); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-string">'A'</span>; i < <span class="hljs-string">'z'</span>; i++) { mDatas.add(<span class="hljs-string">""</span> + (<span class="hljs-keyword">char</span>) i); } } class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> MyViewHolder <span class="hljs-title">onCreateViewHolder</span>(ViewGroup parent, <span class="hljs-keyword">int</span> viewType) { MyViewHolder holder = <span class="hljs-keyword">new</span> MyViewHolder(LayoutInflater.from( HomeActivity.<span class="hljs-keyword">this</span>).inflate(R.layout.item_home, parent, <span class="hljs-keyword">false</span>)); <span class="hljs-keyword">return</span> holder; } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onBindViewHolder</span>(MyViewHolder holder, <span class="hljs-keyword">int</span> position) { holder.tv.setText(mDatas.get(position)); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getItemCount</span>() { <span class="hljs-keyword">return</span> mDatas.size(); } class MyViewHolder extends ViewHolder { TextView tv; <span class="hljs-keyword">public</span> <span class="hljs-title">MyViewHolder</span>(View view) { <span class="hljs-keyword">super</span>(view); tv = (TextView) view.findViewById(R.id.id_num); } } } }` Activity的布局文件 `<span class="hljs-tag"><<span class="hljs-title">RelativeLayout</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span> <span class="hljs-attribute">xmlns:tools</span>=<span class="hljs-value">"http://schemas.android.com/tools"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">android.support.v7.widget.RecyclerView </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_recyclerview"</span> <span class="hljs-attribute">android:divider</span>=<span class="hljs-value">"#ffff0000"</span> <span class="hljs-attribute">android:dividerHeight</span>=<span class="hljs-value">"10dp"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">RelativeLayout</span>></span>` Item的布局文件 `<span class="hljs-pi"><?xml version="1.0" encoding="utf-8"?></span> <span class="hljs-tag"><<span class="hljs-title">FrameLayout</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#44ff0000"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_num"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"50dp"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"1"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">FrameLayout</span>></span>` 这么看起来用法与ListView的代码基本一致哈~~ 看下效果图: ...

2017年6月20日 · 15 分钟 · 天边的星星

ScrollView下,ListView生存之道

首先讲一下我遇到的需求吧,页面是这样的,上边有东西,中间是列表,下边还有东西。首先我看到列表立刻就想到了用ListView,但是页面有限,只能用ScrollView包一下。想到就做呗。我就在ScrollView里面加了一个ListView, ListView设置的是wapcontent,这样就出现了ListView数据只显示出了一行。好的,解决问题的方案就来了。 一.设置scrollView中的ListView内容全部显示,不能滑动,将滑动交给scrollView去做。 做法:在设置adapter之前,重新计算ListView的高度,我这里写了一个方法: java代码 [![](http://www.eyeandroid.com/source/plugin/milu_hightLight/help.png)](http://www.eyeandroid.com/) - <span class="comment">/**</span> - <span class="comment">* 动态设置listView的高度</span> - <span class="comment">* count 总条目</span> - <span class="comment">*/</span> - <span class="keyword">private</span> <span class="keyword">void</span> setListViewHeight(ListView listView, BaseAdapter adapter, - <span class="keyword">int</span> count) { - <span class="keyword">int</span> totalHeight = <span class="number"></span>; - <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number"></span>; i < count; i++) { - View listItem = adapter.getView(i, <span class="keyword">null</span>, listView); - listItem.measure(<span class="number"></span>, <span class="number"></span>); - totalHeight += listItem.getMeasuredHeight(); - } - - ViewGroup.LayoutParams params = listView.getLayoutParams(); - params.height = totalHeight + (listView.getDividerHeight() * count); - listView.setLayoutParams(params); - } 这样做的前提条件是布局文件中ListView的高度要指定,这样才能重新计算,不要设成wapcontent! ...

2015年6月1日 · 5 分钟 · 天边的星星

Android RecyclerView 使用完全解析 体验艺术般的控件

概述 RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。 据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。 那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。 你想要控制其显示的方式,请通过布局管理器LayoutManager 你想要控制Item间的间隔(可绘制),请通过ItemDecoration 你想要控制Item增删的动画,请通过ItemAnimator 你想要控制点击、长按事件,请自己写(擦,这点尼玛。) 基本使用 鉴于我们对于ListView的使用特别的熟悉,对比下RecyclerView的使用代码: `mRecyclerView = findView(R.id.id_recyclerview); &lt;span class="hljs-comment">//设置布局管理器&lt;/span> mRecyclerView.setLayoutManager(layout); &lt;span class="hljs-comment">//设置adapter&lt;/span> mRecyclerView.setAdapter(adapter) &lt;span class="hljs-comment">//设置Item增加、移除动画&lt;/span> mRecyclerView.setItemAnimator(&lt;span class="hljs-keyword">new&lt;/span> DefaultItemAnimator()); &lt;span class="hljs-comment">//添加分割线&lt;/span> mRecyclerView.addItemDecoration(&lt;span class="hljs-keyword">new&lt;/span> DividerItemDecoration( getActivity(), DividerItemDecoration.HORIZONTAL_LIST));` ok,相比较于ListView的代码,ListView可能只需要去设置一个adapter就能正常使用了。而RecyclerView基本需要上面一系列的步骤,那么为什么会添加这么多的步骤呢? 那么就必须解释下RecyclerView的这个名字了,从它类名上看,RecyclerView代表的意义是,我只管Recycler View,也就是说RecyclerView只管回收与复用View,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现ListView,GirdView,瀑布流等效果)。 Just like ListView Activity `&lt;span class="hljs-keyword">package&lt;/span> com.zhy.sample.demo_recyclerview; &lt;span class="hljs-keyword">import&lt;/span> java.util.ArrayList; &lt;span class="hljs-keyword">import&lt;/span> java.util.List; &lt;span class="hljs-keyword">import&lt;/span> android.os.Bundle; &lt;span class="hljs-keyword">import&lt;/span> android.support.v7.app.ActionBarActivity; &lt;span class="hljs-keyword">import&lt;/span> android.support.v7.widget.LinearLayoutManager; &lt;span class="hljs-keyword">import&lt;/span> android.support.v7.widget.RecyclerView; &lt;span class="hljs-keyword">import&lt;/span> android.support.v7.widget.RecyclerView.ViewHolder; &lt;span class="hljs-keyword">import&lt;/span> android.view.LayoutInflater; &lt;span class="hljs-keyword">import&lt;/span> android.view.View; &lt;span class="hljs-keyword">import&lt;/span> android.view.ViewGroup; &lt;span class="hljs-keyword">import&lt;/span> android.widget.TextView; &lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-class">&lt;span class="hljs-keyword">class&lt;/span> &lt;span class="hljs-title">HomeActivity&lt;/span> &lt;span class="hljs-keyword">extends&lt;/span> &lt;span class="hljs-title">ActionBarActivity&lt;/span> {&lt;/span> &lt;span class="hljs-keyword">private&lt;/span> RecyclerView mRecyclerView; &lt;span class="hljs-keyword">private&lt;/span> List&lt;String&gt; mDatas; &lt;span class="hljs-keyword">private&lt;/span> HomeAdapter mAdapter; &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-keyword">protected&lt;/span> &lt;span class="hljs-keyword">void&lt;/span> &lt;span class="hljs-title">onCreate&lt;/span>(Bundle savedInstanceState) { &lt;span class="hljs-keyword">super&lt;/span>.onCreate(savedInstanceState); setContentView(R.layout.activity_single_recyclerview); initData(); mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); mRecyclerView.setLayoutManager(&lt;span class="hljs-keyword">new&lt;/span> LinearLayoutManager(&lt;span class="hljs-keyword">this&lt;/span>)); mRecyclerView.setAdapter(mAdapter = &lt;span class="hljs-keyword">new&lt;/span> HomeAdapter()); } &lt;span class="hljs-keyword">protected&lt;/span> &lt;span class="hljs-keyword">void&lt;/span> &lt;span class="hljs-title">initData&lt;/span>() { mDatas = &lt;span class="hljs-keyword">new&lt;/span> ArrayList&lt;String&gt;(); &lt;span class="hljs-keyword">for&lt;/span> (&lt;span class="hljs-keyword">int&lt;/span> i = &lt;span class="hljs-string">'A'&lt;/span>; i &lt; &lt;span class="hljs-string">'z'&lt;/span>; i++) { mDatas.add(&lt;span class="hljs-string">""&lt;/span> + (&lt;span class="hljs-keyword">char&lt;/span>) i); } } class HomeAdapter extends RecyclerView.Adapter&lt;HomeAdapter.MyViewHolder&gt; { &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-keyword">public&lt;/span> MyViewHolder &lt;span class="hljs-title">onCreateViewHolder&lt;/span>(ViewGroup parent, &lt;span class="hljs-keyword">int&lt;/span> viewType) { MyViewHolder holder = &lt;span class="hljs-keyword">new&lt;/span> MyViewHolder(LayoutInflater.from( HomeActivity.&lt;span class="hljs-keyword">this&lt;/span>).inflate(R.layout.item_home, parent, &lt;span class="hljs-keyword">false&lt;/span>)); &lt;span class="hljs-keyword">return&lt;/span> holder; } &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-keyword">void&lt;/span> &lt;span class="hljs-title">onBindViewHolder&lt;/span>(MyViewHolder holder, &lt;span class="hljs-keyword">int&lt;/span> position) { holder.tv.setText(mDatas.get(position)); } &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-keyword">int&lt;/span> &lt;span class="hljs-title">getItemCount&lt;/span>() { &lt;span class="hljs-keyword">return&lt;/span> mDatas.size(); } class MyViewHolder extends ViewHolder { TextView tv; &lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-title">MyViewHolder&lt;/span>(View view) { &lt;span class="hljs-keyword">super&lt;/span>(view); tv = (TextView) view.findViewById(R.id.id_num); } } } }` Activity的布局文件 `&lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">RelativeLayout&lt;/span> &lt;span class="hljs-attribute">xmlns:android&lt;/span>=&lt;span class="hljs-value">"http://schemas.android.com/apk/res/android"&lt;/span> &lt;span class="hljs-attribute">xmlns:tools&lt;/span>=&lt;span class="hljs-value">"http://schemas.android.com/tools"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &gt;&lt;/span> &lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">android.support.v7.widget.RecyclerView &lt;/span> &lt;span class="hljs-attribute">android:id&lt;/span>=&lt;span class="hljs-value">"@+id/id_recyclerview"&lt;/span> &lt;span class="hljs-attribute">android:divider&lt;/span>=&lt;span class="hljs-value">"#ffff0000"&lt;/span> &lt;span class="hljs-attribute">android:dividerHeight&lt;/span>=&lt;span class="hljs-value">"10dp"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> /&gt;&lt;/span> &lt;span class="hljs-tag">&lt;/&lt;span class="hljs-title">RelativeLayout&lt;/span>&gt;&lt;/span>` Item的布局文件 `&lt;span class="hljs-pi">&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;/span> &lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">FrameLayout&lt;/span> &lt;span class="hljs-attribute">xmlns:android&lt;/span>=&lt;span class="hljs-value">"http://schemas.android.com/apk/res/android"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:background&lt;/span>=&lt;span class="hljs-value">"#44ff0000"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"wrap_content"&lt;/span> &gt;&lt;/span> &lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">TextView &lt;/span> &lt;span class="hljs-attribute">android:id&lt;/span>=&lt;span class="hljs-value">"@+id/id_num"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"50dp"&lt;/span> &lt;span class="hljs-attribute">android:gravity&lt;/span>=&lt;span class="hljs-value">"center"&lt;/span> &lt;span class="hljs-attribute">android:text&lt;/span>=&lt;span class="hljs-value">"1"&lt;/span> /&gt;&lt;/span> &lt;span class="hljs-tag">&lt;/&lt;span class="hljs-title">FrameLayout&lt;/span>&gt;&lt;/span>` 这么看起来用法与ListView的代码基本一致哈~~ 看下效果图: ...

2015年5月19日 · 10 分钟 · 天边的星星

Android — RecyclerView

“A flexible view for providing a limited window into a large data set.” 可以说是ListView的升级版,ListVie中我们需要自己写ViewHolder,当然你也可以不写,是在RecylerView中,是要让写的哟~RecyclerView适用于无法在一个屏幕范围内展现格式一样的数据时,需要用多行或多列来展示。例如展示联系人,图片,视频等。用户需要滑动屏幕来查看数据,这时RecyclerView的特性就有用武之地了。比如,当用户滑动使当前一个可视的Item滑出屏幕,这个Item的视图将会被回收并在一个新Item进入可视范围后重新被使用。可回收利用View是个很实用的功能,它不仅可以减少CPU不断inflate View的开销,而且可以节省缓存View的内存开销。 RecylerView还有一大特色,就是动画! RecyclerView不再负责显示工作 和ListView不一样的是,RecyclerView不再负责Item的摆放等显示方面的功能。所有和布局、绘制等方面的工作都其拆分成不同的类进行管理。所以开发者可以自定义各种各样满足定制需求的的功能类。 RecyclerView.Adapter <td valign="top" width="454"> 托管数据集合,为每个Item创建视图 </td> </tr> <tr> <td valign="top" width="326"> RecyclerView.ViewHolder </td> <td valign="top" width="454"> 承载Item视图的子视图 </td> </tr> <tr> <td valign="top" width="326"> RecyclerView.LayoutManager </td> <td valign="top" width="454"> 负责Item视图的布局 </td> </tr> <tr> <td valign="top" width="326"> RecyclerView.ItemDecoration </td> <td valign="top" width="454"> 为每个Item视图添加子视图,在Demo中被用来绘制Divider </td> </tr> <tr> <td valign="top" width="326"> RecyclerView.ItemAnimator </td> <td valign="top" width="454"> 负责添加、删除数据时的动画效果 </td> </tr> ViewHolder 关于ViewHolder,Google早就推荐开发者使用,但也只是建议。但是现在,RecyclerView.Adapter最终要求开发者必须使用ViewHolder。 ...

2015年5月8日 · 3 分钟 · 天边的星星

Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

转载(http://blog.csdn.net/xiaanming/article/details/18311877) 今天还是给大家带来自定义控件的编写,自定义一个ListView的左右滑动删除Item的效果,这个效果之前已经实现过了,有兴趣的可以看下Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,之前使用的是滑动类Scroller来实现的,但是看了下通知栏的左右滑动删除效果,确实很棒,当我们滑动Item超过一半的时候,item的透明度就变成了0,我们就知道抬起手指的时候item就被删除了,当item的透明度不为0的时候,我们抬起手指Item会回到起始位置,这样我们就知道拖动到什么位置item会删除,什么位置Item不删除,用户体验更好了,还有一个效果,就是我们滑动删除了item的时候,ListView的其他item会出现向上或者向下滚动的效果,感觉效果很棒,所以在GitHub上面搜索了下,发现很多开源库都有这个效果,比如ListViewAnimations, android-swipelistview等等,我看了下实现原理,使用的是Jake Wharton的动画开源库NineOldAndroids,这个库究竟是干嘛的呢?在API3.0(Honeycomb), SDK新增了一个android.animation包,里面的类是实现动画效果相关的类,通过Honeycomb API,能够实现非常复杂的动画效果,但是如果开发者想在3.0以下使用这一套API, 则需要使用开源框架Nine Old Androids,在这个库中会根据我们运行的机器判断其SDK版本,如果是API3.0以上则使用Android自带的动画类,否则就使用Nine Old Androids库中,这是一个兼容库,接下来我们就来看看这个效果的具体实现吧 实现该效果的主要思路 先根据手指触摸的点来获取点击的是ListView的哪一个Item 当手指在屏幕上面滑动的时候,我们要使得Item跟随手指的滑动而滑动 当我们抬起手指的时候,我们根据滑动的距离或者手指在屏幕上面的速度来判断Item是滑出屏幕还是滑动至其实位置 Item滑出屏幕时,使ListView的其他item产生向上挤压或者向下挤压的效果 大致的思路这是这四步,其中的一些细节接下来我会一一为大家解答的,接下来我们就用代码来实现这种效果吧 首先我们新建一个工程,叫Swipedismisslistview,我们需要将Nine Old Androids这个库引入到工程,大家可以去https://github.com/JakeWharton/NineOldAndroids下载,可以使用Jar包,也可以使用工程库的形式引入到我们自己的工程,我们还需要自定义一个ListView,我们先看代码然后给大家讲解下具体的功能实现 **[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/18311877#)[copy](http://blog.csdn.net/xiaanming/article/details/18311877#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/159353)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/159353/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.example.swipedismisslistview; - - <span class="keyword">import</span> <span class="keyword">static</span> com.nineoldandroids.view.ViewHelper.setAlpha; - <span class="keyword">import</span> <span class="keyword">static</span> com.nineoldandroids.view.ViewHelper.setTranslationX; - <span class="keyword">import</span> android.content.Context; - <span class="keyword">import</span> android.util.AttributeSet; - <span class="keyword">import</span> android.view.MotionEvent; - <span class="keyword">import</span> android.view.VelocityTracker; - <span class="keyword">import</span> android.view.View; - <span class="keyword">import</span> android.view.ViewConfiguration; - <span class="keyword">import</span> android.view.ViewGroup; - <span class="keyword">import</span> android.widget.AdapterView; - <span class="keyword">import</span> android.widget.ListView; - - <span class="keyword">import</span> com.nineoldandroids.animation.Animator; - <span class="keyword">import</span> com.nineoldandroids.animation.AnimatorListenerAdapter; - <span class="keyword">import</span> com.nineoldandroids.animation.ValueAnimator; - <span class="keyword">import</span> com.nineoldandroids.view.ViewHelper; - <span class="keyword">import</span> com.nineoldandroids.view.ViewPropertyAnimator; - <span class="comment">/**</span> - <span class="comment"> * @blog http://blog.csdn.net/xiaanming</span> - <span class="comment"> * </span> - <span class="comment"> * @author xiaanming</span> - <span class="comment"> *</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">class</span> SwipeDismissListView <span class="keyword">extends</span> ListView { - <span class="comment">/**</span> - <span class="comment"> * 认为是用户滑动的最小距离</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mSlop; - <span class="comment">/**</span> - <span class="comment"> * 滑动的最小速度</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mMinFlingVelocity; - <span class="comment">/**</span> - <span class="comment"> * 滑动的最大速度</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mMaxFlingVelocity; - <span class="comment">/**</span> - <span class="comment"> * 执行动画的时间</span> - <span class="comment"> */</span> - <span class="keyword">protected</span> <span class="keyword">long</span> mAnimationTime = <span class="number">150</span>; - <span class="comment">/**</span> - <span class="comment"> * 用来标记用户是否正在滑动中</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> mSwiping; - <span class="comment">/**</span> - <span class="comment"> * 滑动速度检测类</span> - <span class="comment"> */</span> - <span class="keyword">private</span> VelocityTracker mVelocityTracker; - <span class="comment">/**</span> - <span class="comment"> * 手指按下的position</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mDownPosition; - <span class="comment">/**</span> - <span class="comment"> * 按下的item对应的View</span> - <span class="comment"> */</span> - <span class="keyword">private</span> View mDownView; - <span class="keyword">private</span> <span class="keyword">float</span> mDownX; - <span class="keyword">private</span> <span class="keyword">float</span> mDownY; - <span class="comment">/**</span> - <span class="comment"> * item的宽度</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mViewWidth; - <span class="comment">/**</span> - <span class="comment"> * 当ListView的Item滑出界面回调的接口</span> - <span class="comment"> */</span> - <span class="keyword">private</span> OnDismissCallback onDismissCallback; - - <span class="comment">/**</span> - <span class="comment"> * 设置动画时间</span> - <span class="comment"> * </span> - <span class="comment"> * @param mAnimationTime</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">void</span> setmAnimationTime(<span class="keyword">long</span> mAnimationTime) { - <span class="keyword">this</span>.mAnimationTime = mAnimationTime; - } - - <span class="comment">/**</span> - <span class="comment"> * 设置删除回调接口</span> - <span class="comment"> * </span> - <span class="comment"> * @param onDismissCallback</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">void</span> setOnDismissCallback(OnDismissCallback onDismissCallback) { - <span class="keyword">this</span>.onDismissCallback = onDismissCallback; - } - - <span class="keyword">public</span> SwipeDismissListView(Context context) { - <span class="keyword">this</span>(context, <span class="keyword">null</span>); - } - - <span class="keyword">public</span> SwipeDismissListView(Context context, AttributeSet attrs) { - <span class="keyword">this</span>(context, attrs, <span class="number"></span>); - } - - <span class="keyword">public</span> SwipeDismissListView(Context context, AttributeSet attrs, - <span class="keyword">int</span> defStyle) { - <span class="keyword">super</span>(context, attrs, defStyle); - - ViewConfiguration vc = ViewConfiguration.get(context); - mSlop = vc.getScaledTouchSlop(); - mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * <span class="number">8</span>; <span class="comment">//获取滑动的最小速度</span> - mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); <span class="comment">//获取滑动的最大速度</span> - } - - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">boolean</span> onTouchEvent(MotionEvent ev) { - <span class="keyword">switch</span> (ev.getAction()) { - <span class="keyword">case</span> MotionEvent.ACTION_DOWN: - handleActionDown(ev); - <span class="keyword">break</span>; - <span class="keyword">case</span> MotionEvent.ACTION_MOVE: - <span class="keyword">return</span> handleActionMove(ev); - <span class="keyword">case</span> MotionEvent.ACTION_UP: - handleActionUp(ev); - <span class="keyword">break</span>; - } - <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(ev); - } - - <span class="comment">/**</span> - <span class="comment"> * 按下事件处理</span> - <span class="comment"> * </span> - <span class="comment"> * @param ev</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> handleActionDown(MotionEvent ev) { - mDownX = ev.getX(); - mDownY = ev.getY(); - - mDownPosition = pointToPosition((<span class="keyword">int</span>) mDownX, (<span class="keyword">int</span>) mDownY); - - <span class="keyword">if</span> (mDownPosition == AdapterView.INVALID_POSITION) { - <span class="keyword">return</span>; - } - - mDownView = getChildAt(mDownPosition &#8211; getFirstVisiblePosition()); - - <span class="keyword">if</span> (mDownView != <span class="keyword">null</span>) { - mViewWidth = mDownView.getWidth(); - } - - <span class="comment">//加入速度检测</span> - mVelocityTracker = VelocityTracker.obtain(); - mVelocityTracker.addMovement(ev); - } - - - <span class="comment">/**</span> - <span class="comment"> * 处理手指滑动的方法</span> - <span class="comment"> * </span> - <span class="comment"> * @param ev</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> handleActionMove(MotionEvent ev) { - <span class="keyword">if</span> (mVelocityTracker == <span class="keyword">null</span> || mDownView == <span class="keyword">null</span>) { - <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(ev); - } - - <span class="comment">// 获取X方向滑动的距离</span> - <span class="keyword">float</span> deltaX = ev.getX() &#8211; mDownX; - <span class="keyword">float</span> deltaY = ev.getY() &#8211; mDownY; - - <span class="comment">// X方向滑动的距离大于mSlop并且Y方向滑动的距离小于mSlop,表示可以滑动</span> - <span class="keyword">if</span> (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < mSlop) { - mSwiping = <span class="keyword">true</span>; - - <span class="comment">//当手指滑动item,取消item的点击事件,不然我们滑动Item也伴随着item点击事件的发生</span> - MotionEvent cancelEvent = MotionEvent.obtain(ev); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL | - (ev.getActionIndex()<< MotionEvent.ACTION_POINTER_INDEX_SHIFT)); - onTouchEvent(cancelEvent); - } - - <span class="keyword">if</span> (mSwiping) { - <span class="comment">// 跟谁手指移动item</span> - ViewHelper.setTranslationX(mDownView, deltaX); - <span class="comment">// 透明度渐变</span> - ViewHelper.setAlpha(mDownView, Math.max(0f, Math.min(1f, 1f &#8211; 2f * Math.abs(deltaX)/ mViewWidth))); - - <span class="comment">// 手指滑动的时候,返回true,表示SwipeDismissListView自己处理onTouchEvent,其他的就交给父类来处理</span> - <span class="keyword">return</span> <span class="keyword">true</span>; - } - - <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(ev); - - } - - <span class="comment">/**</span> - <span class="comment"> * 手指抬起的事件处理</span> - <span class="comment"> * @param ev</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> handleActionUp(MotionEvent ev) { - <span class="keyword">if</span> (mVelocityTracker == <span class="keyword">null</span> || mDownView == <span class="keyword">null</span>|| !mSwiping) { - <span class="keyword">return</span>; - } - - <span class="keyword">float</span> deltaX = ev.getX() &#8211; mDownX; - - <span class="comment">//通过滑动的距离计算出X,Y方向的速度</span> - mVelocityTracker.computeCurrentVelocity(<span class="number">1000</span>); - <span class="keyword">float</span> velocityX = Math.abs(mVelocityTracker.getXVelocity()); - <span class="keyword">float</span> velocityY = Math.abs(mVelocityTracker.getYVelocity()); - - <span class="keyword">boolean</span> dismiss = <span class="keyword">false</span>; <span class="comment">//item是否要滑出屏幕</span> - <span class="keyword">boolean</span> dismissRight = <span class="keyword">false</span>;<span class="comment">//是否往右边删除</span> - - <span class="comment">//当拖动item的距离大于item的一半,item滑出屏幕</span> - <span class="keyword">if</span> (Math.abs(deltaX) > mViewWidth / <span class="number">2</span>) { - dismiss = <span class="keyword">true</span>; - dismissRight = deltaX > <span class="number"></span>; - - <span class="comment">//手指在屏幕滑动的速度在某个范围内,也使得item滑出屏幕</span> - } <span class="keyword">else</span> <span class="keyword">if</span> (mMinFlingVelocity <= velocityX - && velocityX <= mMaxFlingVelocity && velocityY < velocityX) { - dismiss = <span class="keyword">true</span>; - dismissRight = mVelocityTracker.getXVelocity() > <span class="number"></span>; - } - - <span class="keyword">if</span> (dismiss) { - ViewPropertyAnimator.animate(mDownView) - .translationX(dismissRight ? mViewWidth : -mViewWidth)<span class="comment">//X轴方向的移动距离</span> - .alpha(<span class="number"></span>) - .setDuration(mAnimationTime) - .setListener(<span class="keyword">new</span> AnimatorListenerAdapter() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onAnimationEnd(Animator animation) { - <span class="comment">//Item滑出界面之后执行删除</span> - performDismiss(mDownView, mDownPosition); - } - }); - } <span class="keyword">else</span> { - <span class="comment">//将item滑动至开始位置</span> - ViewPropertyAnimator.animate(mDownView) - .translationX(<span class="number"></span>) - .alpha(<span class="number">1</span>) - .setDuration(mAnimationTime).setListener(<span class="keyword">null</span>); - } - - <span class="comment">//移除速度检测</span> - <span class="keyword">if</span>(mVelocityTracker != <span class="keyword">null</span>){ - mVelocityTracker.recycle(); - mVelocityTracker = <span class="keyword">null</span>; - } - - mSwiping = <span class="keyword">false</span>; - } - - - - <span class="comment">/**</span> - <span class="comment"> * 在此方法中执行item删除之后,其他的item向上或者向下滚动的动画,并且将position回调到方法onDismiss()中</span> - <span class="comment"> * @param dismissView</span> - <span class="comment"> * @param dismissPosition</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> performDismiss(<span class="keyword">final</span> View dismissView, <span class="keyword">final</span> <span class="keyword">int</span> dismissPosition) { - <span class="keyword">final</span> ViewGroup.LayoutParams lp = dismissView.getLayoutParams();<span class="comment">//获取item的布局参数</span> - <span class="keyword">final</span> <span class="keyword">int</span> originalHeight = dismissView.getHeight();<span class="comment">//item的高度</span> - - ValueAnimator animator = ValueAnimator.ofInt(originalHeight, <span class="number"></span>).setDuration(mAnimationTime); - animator.start(); - - animator.addListener(<span class="keyword">new</span> AnimatorListenerAdapter() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onAnimationEnd(Animator animation) { - <span class="keyword">if</span> (onDismissCallback != <span class="keyword">null</span>) { - onDismissCallback.onDismiss(dismissPosition); - } - - <span class="comment">//这段代码很重要,因为我们并没有将item从ListView中移除,而是将item的高度设置为0</span> - <span class="comment">//所以我们在动画执行完毕之后将item设置回来</span> - ViewHelper.setAlpha(dismissView, 1f); - ViewHelper.setTranslationX(dismissView, <span class="number"></span>); - ViewGroup.LayoutParams lp = dismissView.getLayoutParams(); - lp.height = originalHeight; - dismissView.setLayoutParams(lp); - - } - }); - - animator.addUpdateListener(<span class="keyword">new</span> ValueAnimator.AnimatorUpdateListener() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onAnimationUpdate(ValueAnimator valueAnimator) { - <span class="comment">//这段代码的效果是ListView删除某item之后,其他的item向上滑动的效果</span> - lp.height = (Integer) valueAnimator.getAnimatedValue(); - dismissView.setLayoutParams(lp); - } - }); - - } - - <span class="comment">/**</span> - <span class="comment"> * 删除的回调接口</span> - <span class="comment"> * </span> - <span class="comment"> * @author xiaanming</span> - <span class="comment"> * </span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">interface</span> OnDismissCallback { - <span class="keyword">public</span> <span class="keyword">void</span> onDismiss(<span class="keyword">int</span> dismissPosition); - } - - } 看过Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果你会发现,这个自定义的SwipeDismissListView只重写了onTouchEvent()方法,其实我们重写这一个方法就能实现我们需要的效果 ...

2015年3月7日 · 9 分钟 · 天边的星星

github源码分享PinnedSectionListView:分组的listView滑动中固定组标题的实现

在很多应用中,看到这样的listview:listview滑动过程中分组标题固定在上方,当第二个组滑上来时,第一个组才跟着上滑,下一个组固定,直到该组也滑出上边缘。世上无难事只怕有心人,在github上就有人做出来了,而且效果很好(后来发现安卓自带应用中联系人应用就是这样的,估计github的作者也是仿照着联系人做出来的吧)。 先看截图: PinnedSectionListView继承自listview,众所周知listview的每个子view都是按顺序跟着滚动的,要实现联系人listview的效果还真的找不到思路。看了PinnedSectionListView之后,感觉要改造一个现有的控件,一般都是通过重绘子view来实现的。ViewGroup(ListView继承自它)重绘子view的方法是dispatchDraw。 看看PinnedSectionListView在dispatchDraw中有那些特别的处理: 1 <div class="line number2 index1 alt1"> 2 </div> <div class="line number3 index2 alt2"> 3 </div> <div class="line number4 index3 alt1"> 4 </div> <div class="line number5 index4 alt2"> 5 </div> <div class="line number6 index5 alt1"> 6 </div> <div class="line number7 index6 alt2"> 7 </div> <div class="line number8 index7 alt1"> 8 </div> <div class="line number9 index8 alt2"> 9 </div> <div class="line number10 index9 alt1"> 10 </div> <div class="line number11 index10 alt2"> 11 </div> <div class="line number12 index11 alt1"> 12 </div> <div class="line number13 index12 alt2"> 13 </div> <div class="line number14 index13 alt1"> 14 </div> <div class="line number15 index14 alt2"> 15 </div> <div class="line number16 index15 alt1"> 16 </div> <div class="line number17 index16 alt2"> 17 </div> <div class="line number18 index17 alt1"> 18 </div> <div class="line number19 index18 alt2"> 19 </div> <div class="line number20 index19 alt1"> 20 </div> <div class="line number21 index20 alt2"> 21 </div> <div class="line number22 index21 alt1"> 22 </div> <div class="line number23 index22 alt2"> 23 </div> <div class="line number24 index23 alt1"> 24 </div> <div class="line number25 index24 alt2"> 25 </div> </td> <td class="code"> <div class="container"> <div class="line number1 index0 alt2"> `@Override` </div> <div class="line number2 index1 alt1"> `protected void dispatchDraw(Canvas canvas) {` </div> <div class="line number3 index2 alt2"> ` ``super``.dispatchDraw(canvas);` </div> <div class="line number4 index3 alt1"> ` ``if` `(mPinnedSection != ``null``) {` </div> <div class="line number5 index4 alt2"> ` ``// prepare variables` </div> <div class="line number6 index5 alt1"> ` ``int pLeft = getListPaddingLeft();` </div> <div class="line number7 index6 alt2"> ` ``int pTop = getListPaddingTop();` </div> <div class="line number8 index7 alt1"> ` ``View view = mPinnedSection.view;` </div> <div class="line number9 index8 alt2"> ` ``// draw child` </div> <div class="line number10 index9 alt1"> ` ``canvas.save();` </div> <div class="line number11 index10 alt2"> ` ``int clipHeight = view.getHeight() +` </div> <div class="line number12 index11 alt1"> ` ``(mShadowDrawable == ``null` `? 0 : Math.min(mShadowHeight, mSectionsDistanceY));` </div> <div class="line number13 index12 alt2"> ` ``canvas.clipRect(pLeft, pTop, pLeft + view.getWidth(), pTop + clipHeight);` </div> <div class="line number14 index13 alt1"> ` ``canvas.translate(pLeft, pTop + mTranslateY);` </div> <div class="line number15 index14 alt2"> ` ``drawChild(canvas, mPinnedSection.view, getDrawingTime());` </div> <div class="line number16 index15 alt1"> ` ``if` `(mShadowDrawable != ``null` `&& mSectionsDistanceY &gt; 0) {` </div> <div class="line number17 index16 alt2"> ` ``mShadowDrawable.setBounds(mPinnedSection.view.getLeft(),` </div> <div class="line number18 index17 alt1"> ` ``mPinnedSection.view.getBottom(),` </div> <div class="line number19 index18 alt2"> ` ``mPinnedSection.view.getRight(),` </div> <div class="line number20 index19 alt1"> ` ``mPinnedSection.view.getBottom() + mShadowHeight);` </div> <div class="line number21 index20 alt2"> ` ``mShadowDrawable.draw(canvas);` </div> <div class="line number22 index21 alt1"> ` ``}` </div> <div class="line number23 index22 alt2"> ` ``canvas.restore();` </div> <div class="line number24 index23 alt1"> ` ``}` </div> <div class="line number25 index24 alt2"> `}` </div> </div> </td> </tr> </table> 关键在于```canvas.translate(pLeft, pTop + mTranslateY);意思是在绘制mPinnedSection的时候,listview滑动了多长的距离,就将canvas移动多少的距离,使mPinnedSection`始终在可见的范围内固定不变。 ...

2015年3月4日 · 4 分钟 · 天边的星星

Android学习小Demo(12)TodoList实现ListView的分组实现

 很多情况下, 我们想要ListView上面展示的东西是可以分组的,比如联系人列表,国家列表啊,这样看起来数据的展现比较有层次感,而且也有助于我们快速定位到某一个具体的条目上,具体效果请看下图: 这是前面TodoList小demo的MainActivity,主要是来展现用户添加的任务的,在原来的基础上添加了分组的效果。 接下来我们具体来讲一下这个效果是怎么实现的。 这是利用开源库StickyListHeaders(传送门:https://github.com/emilsjolander/StickyListHeaders)来实现的,这个实现的效果是基于ListView的,而其实也有关于GridView而实现的分组的效果,大家可以参考一下xiaanming的博客(他的文章名字都很长。。。): Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果 0)关于如何导进开源库,大家请参考:如何导进开源库StickyListHeaders 1)然后,我们要想清楚一件事情,即分组的ListView,是包含两部分:Header 和 Item,所以相对应的我们也要为其定义两个Layout,如下: 1.1)task_header.xml **[html]** [view plain](http://blog.csdn.net/linmiansheng/article/details/20747775#)[copy](http://blog.csdn.net/linmiansheng/article/details/20747775#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/224769)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/224769/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="tag"><?</span><span class="tag-name">xml</span> <span class="attribute">version</span>=<span class="attribute-value">&#8220;1.0&#8221;</span> <span class="attribute">encoding</span>=<span class="attribute-value">&#8220;utf-8&#8221;</span><span class="tag">?></span> - <span class="tag"><</span><span class="tag-name">RelativeLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:background</span>=<span class="attribute-value">&#8220;@drawable/header_selector&#8221;</span> <span class="tag">></span> - - <span class="tag"><</span><span class="tag-name">TextView</span> - <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/tvHeader&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:layout_gravity</span>=<span class="attribute-value">&#8220;start|left&#8221;</span> - <span class="attribute">android:padding</span>=<span class="attribute-value">&#8220;5dp&#8221;</span> - <span class="attribute">android:textColor</span>=<span class="attribute-value">&#8220;@android:color/white&#8221;</span> - <span class="attribute">android:textSize</span>=<span class="attribute-value">&#8220;17sp&#8221;</span> - <span class="attribute">android:textStyle</span>=<span class="attribute-value">&#8220;bold&#8221;</span> <span class="tag">/></span> - - <span class="tag"></</span><span class="tag-name">RelativeLayout</span><span class="tag">></span> 因为我们在Header上面只是展现一个日期,所以我们只需要一个TextView即可。 ...

2015年1月20日 · 7 分钟 · 天边的星星

android ListView 设置分割线 Divider

这是一个极其隐蔽的 BUG 首先需求是:用 ColorDrawable 设置 ListView 分割线 ``` listView.setDivider(new ColorDrawable(0xffd4d5d6)); ``` 这样原理上绝对说得过去,但是你怎么都看不到效果,为什么呢,看源码吧! ![复制代码](http://common.cnblogs.com/images/copycode.gif) public void setDivider(Drawable divider) { if (divider != null) { mDividerHeight = divider.getIntrinsicHeight(); } else { mDividerHeight = 0; } //.... ![复制代码](http://common.cnblogs.com/images/copycode.gif) mDividerHeight 是分割线的高度,我们再看 [Drawable](eclipse-javadoc:%E2%98%82=MopoGameLauncher/E:%5C/adt-bundle-windows-x86_64-20130219%5C/sdk%5C/platforms%5C/android-17%5C/android.jar%3Candroid.graphics.drawable(Drawable.class%E2%98%83Drawable).getIntrinsicHeight() ``` public int getIntrinsicHeight() { return -1; } ``` 返回 -1,而 ColorDrawable 并没有重载此方法! 有些人运气好,在后面加了一句 listView.setDividerHeight(2); 这样问题就解决了,但是当你把这句放前面,就不知道为什么了! 所以正确方法是: ``` listView.setDivider(new ColorDrawable(0xffd4d5d6)); listView.setDividerHeight(2); ```

2014年11月13日 · 1 分钟 · 天边的星星

JqueryMobile动态生成listView并刷新的方法!

JqueryMobile动态生成listView并刷新的方法! **[javascript]** [view plain](http://blog.csdn.net/zz_mm/article/details/6836503#)[copy](http://blog.csdn.net/zz_mm/article/details/6836503#) <div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">function</span> queryEntfernungen(tx, results) </span> - <span style="color: black;"> alert(<span class="string" style="color: blue;">&#8220;This Hello works&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">var</span> len = results.rows.length; </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// This For works fine</span> </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">for</span> (<span class="keyword" style="font-weight: bold; color: #006699;">var</span> i = 0; i < len; i++) { </span> - <span style="color: black;"> $(<span class="string" style="color: blue;">&#8220;div[data-role=content] ul&#8221;</span>).append(<span class="string" style="color: blue;">&#8216;- <a href=&#8221;&#8216;</span>+results.rows.item(i).name+<span class="string" style="color: blue;">&#8216;&#8221;>&#8217;</span>+results.rows.item(i).name+<span class="string" style="color: blue;">&#8216;</a>&#8217;</span>); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> $(<span class="string" style="color: blue;">&#8220;div[data-role=content] ul&#8221;</span>).listview(<span class="string" style="color: blue;">&#8216;refresh&#8217;</span>); <span class="comment" style="color: #008200;">// This also works</span> </span> 但是下面的方法却也能成功! ...

2014年9月28日 · 2 分钟 · 天边的星星

Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)

本文内容: 1、横向ListView的所有实现思路; 2、其中一个最通用的思路HorizontalListView,并基于横向ListView开发一个简单的相册; 3、实现的横向ListView在点击、浏览时item背景会变色,并解决了listview里setSelected造成item的选择状态混乱的问题。 众所周知,ListView默认的方向是垂直的,但有些时候人们更喜欢横向ListView。纵观整个网络,横向ListView的实现思路如下: 1、在布局里用HorizontalScrollView包含一个ListView,参考这里; 2、利用GridView,把它的行数设为1行; 3、有人继承ListView构造了一个HorizontalScrollListView,参见:这里 4、国外一位大牛继承AdapterView构造的HorizontalListView,这是以上所有方法里本人认为最正统的方法,本文即基于此方法,参见:这里 下面看源码: 这是Activity的布局文件:activity_main.xml **[html]** [view plain](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[copy](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[print](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[?](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/237690)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/237690/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">span</span> <span class="attribute" style="color: red;">style</span>=<span class="attribute-value" style="color: blue;">&#8220;font-family: &#8216;Comic Sans MS&#8217;; font-size: 18px;&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">></span><span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">RelativeLayout</span> <span class="attribute" style="color: red;">xmlns:android</span>=<span class="attribute-value" style="color: blue;">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">xmlns:tools</span>=<span class="attribute-value" style="color: blue;">&#8220;http://schemas.android.com/tools&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_width</span>=<span class="attribute-value" style="color: blue;">&#8220;match_parent&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_height</span>=<span class="attribute-value" style="color: blue;">&#8220;match_parent&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:paddingBottom</span>=<span class="attribute-value" style="color: blue;">&#8220;@dimen/activity_vertical_margin&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:paddingLeft</span>=<span class="attribute-value" style="color: blue;">&#8220;@dimen/activity_horizontal_margin&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:paddingRight</span>=<span class="attribute-value" style="color: blue;">&#8220;@dimen/activity_horizontal_margin&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:paddingTop</span>=<span class="attribute-value" style="color: blue;">&#8220;@dimen/activity_vertical_margin&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">tools:context</span>=<span class="attribute-value" style="color: blue;">&#8220;.MainActivity&#8221;</span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;">></span> </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">org.yanzi.ui.HorizontalListView</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:id</span>=<span class="attribute-value" style="color: blue;">&#8220;@+id/horizon_listview&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_width</span>=<span class="attribute-value" style="color: blue;">&#8220;match_parent&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_height</span>=<span class="attribute-value" style="color: blue;">&#8220;150dip&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_alignParentTop</span>=<span class="attribute-value" style="color: blue;">&#8220;true&#8221;</span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;">></span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">org.yanzi.ui.HorizontalListView</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">ImageView</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:id</span>=<span class="attribute-value" style="color: blue;">&#8220;@+id/image_preview&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_width</span>=<span class="attribute-value" style="color: blue;">&#8220;wrap_content&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_height</span>=<span class="attribute-value" style="color: blue;">&#8220;wrap_content&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_below</span>=<span class="attribute-value" style="color: blue;">&#8220;@id/horizon_listview&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_centerInParent</span>=<span class="attribute-value" style="color: blue;">&#8220;true&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:clickable</span>=<span class="attribute-value" style="color: blue;">&#8220;true&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:background</span>=<span class="attribute-value" style="color: blue;">&#8220;@drawable/selector_imageview_background&#8221;</span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;">/></span> </span> - <span style="color: black;"> <span class="comments" style="color: #008200;"><!&#8211; android:background=&#8221;@android:drawable/ic_menu_gallery&#8221; &#8211;></span> </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">RelativeLayout</span><span class="tag" style="font-weight: bold; color: blue;">></span><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">span</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> 这是横向listview的每个item的布局,图片+文字,horizontal_list_item.xml **[html]** [view plain](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[copy](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[print](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[?](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/237690)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/237690/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">span</span> <span class="attribute" style="color: red;">style</span>=<span class="attribute-value" style="color: blue;">&#8220;font-family: &#8216;Comic Sans MS&#8217;; font-size: 18px;&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">></span><span class="tag" style="font-weight: bold; color: blue;"><?</span><span class="tag-name" style="font-weight: bold; color: blue;">xml</span> <span class="attribute" style="color: red;">version</span>=<span class="attribute-value" style="color: blue;">&#8220;1.0&#8221;</span> <span class="attribute" style="color: red;">encoding</span>=<span class="attribute-value" style="color: blue;">&#8220;utf-8&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">?></span> </span> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">LinearLayout</span> <span class="attribute" style="color: red;">xmlns:android</span>=<span class="attribute-value" style="color: blue;">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_width</span>=<span class="attribute-value" style="color: blue;">&#8220;wrap_content&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_height</span>=<span class="attribute-value" style="color: blue;">&#8220;wrap_content&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:paddingLeft</span>=<span class="attribute-value" style="color: blue;">&#8220;2dip&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:paddingRight</span>=<span class="attribute-value" style="color: blue;">&#8220;2dip&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:paddingTop</span>=<span class="attribute-value" style="color: blue;">&#8220;2dip&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:paddingBottom</span>=<span class="attribute-value" style="color: blue;">&#8220;2dip&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:orientation</span>=<span class="attribute-value" style="color: blue;">&#8220;vertical&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:gravity</span>=<span class="attribute-value" style="color: blue;">&#8220;center&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:clickable</span>=<span class="attribute-value" style="color: blue;">&#8220;true&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:background</span>=<span class="attribute-value" style="color: blue;">&#8220;@drawable/selector_item_background&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">ImageView</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:id</span>=<span class="attribute-value" style="color: blue;">&#8220;@+id/img_list_item&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_width</span>=<span class="attribute-value" style="color: blue;">&#8220;wrap_content&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_height</span>=<span class="attribute-value" style="color: blue;">&#8220;wrap_content&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">/></span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">TextView</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:id</span>=<span class="attribute-value" style="color: blue;">&#8220;@+id/text_list_item&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_width</span>=<span class="attribute-value" style="color: blue;">&#8220;match_parent&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:layout_height</span>=<span class="attribute-value" style="color: blue;">&#8220;wrap_content&#8221;</span> </span> - <span style="color: black;"> <span class="attribute" style="color: red;">android:gravity</span>=<span class="attribute-value" style="color: blue;">&#8220;center&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">/></span> </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">LinearLayout</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">span</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> 下面文件是selector_imageview_background.xml,这是大图片你点击浏览时背景发生变化的selector,没有啥实际作用。 **[html]** [view plain](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[copy](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[print](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[?](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/237690)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/237690/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">span</span> <span class="attribute" style="color: red;">style</span>=<span class="attribute-value" style="color: blue;">&#8220;font-family: &#8216;Comic Sans MS&#8217;; font-size: 18px;&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">></span><span class="tag" style="font-weight: bold; color: blue;"><?</span><span class="tag-name" style="font-weight: bold; color: blue;">xml</span> <span class="attribute" style="color: red;">version</span>=<span class="attribute-value" style="color: blue;">&#8220;1.0&#8221;</span> <span class="attribute" style="color: red;">encoding</span>=<span class="attribute-value" style="color: blue;">&#8220;utf-8&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">?></span> </span> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">selector</span> <span class="attribute" style="color: red;">xmlns:android</span>=<span class="attribute-value" style="color: blue;">&#8220;http://schemas.android.com/apk/res/android&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">item</span> <span class="attribute" style="color: red;">android:drawable</span>=<span class="attribute-value" style="color: blue;">&#8220;@android:color/holo_green_light&#8221;</span> <span class="attribute" style="color: red;">android:state_pressed</span>=<span class="attribute-value" style="color: blue;">&#8220;true&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">/></span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">item</span> <span class="attribute" style="color: red;">android:drawable</span>=<span class="attribute-value" style="color: blue;">&#8220;@android:color/holo_green_light&#8221;</span> <span class="attribute" style="color: red;">android:state_focused</span>=<span class="attribute-value" style="color: blue;">&#8220;true&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">/></span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">item</span> <span class="attribute" style="color: red;">android:drawable</span>=<span class="attribute-value" style="color: blue;">&#8220;@drawable/image_background&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">></span><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">item</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> - <span style="color: black;"><span class="comments" style="color: #008200;"><!&#8211; android:drawable=&#8221;@android:color/transparent&#8221; &#8211;></span> </span> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">selector</span><span class="tag" style="font-weight: bold; color: blue;">></span><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">span</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> 下面是每个item的selector,在focus和select时颜色会发生变化:selector_item_background.xml **[html]** [view plain](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[copy](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[print](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[?](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/237690)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/237690/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">span</span> <span class="attribute" style="color: red;">style</span>=<span class="attribute-value" style="color: blue;">&#8220;font-family: &#8216;Comic Sans MS&#8217;; font-size: 18px;&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">></span><span class="tag" style="font-weight: bold; color: blue;"><?</span><span class="tag-name" style="font-weight: bold; color: blue;">xml</span> <span class="attribute" style="color: red;">version</span>=<span class="attribute-value" style="color: blue;">&#8220;1.0&#8221;</span> <span class="attribute" style="color: red;">encoding</span>=<span class="attribute-value" style="color: blue;">&#8220;utf-8&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">?></span> </span> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">selector</span> <span class="attribute" style="color: red;">xmlns:android</span>=<span class="attribute-value" style="color: blue;">&#8220;http://schemas.android.com/apk/res/android&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">item</span> <span class="attribute" style="color: red;">android:drawable</span>=<span class="attribute-value" style="color: blue;">&#8220;@android:color/holo_red_light&#8221;</span> <span class="attribute" style="color: red;">android:state_selected</span>=<span class="attribute-value" style="color: blue;">&#8220;true&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">/></span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">item</span> <span class="attribute" style="color: red;">android:drawable</span>=<span class="attribute-value" style="color: blue;">&#8220;@android:color/holo_green_dark&#8221;</span> <span class="attribute" style="color: red;">android:state_pressed</span>=<span class="attribute-value" style="color: blue;">&#8220;true&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">/></span> </span> - <span style="color: black;"> <span class="tag" style="font-weight: bold; color: blue;"><</span><span class="tag-name" style="font-weight: bold; color: blue;">item</span> <span class="attribute" style="color: red;">android:drawable</span>=<span class="attribute-value" style="color: blue;">&#8220;@android:color/transparent&#8221;</span><span class="tag" style="font-weight: bold; color: blue;">/></span> </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">selector</span><span class="tag" style="font-weight: bold; color: blue;">></span><span class="tag" style="font-weight: bold; color: blue;"></</span><span class="tag-name" style="font-weight: bold; color: blue;">span</span><span class="tag" style="font-weight: bold; color: blue;">></span> </span> 主程序:MainActivity.java **[java]** [view plain](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[copy](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[print](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[?](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/237690)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/237690/fork) <div> </div> </div> </div> - <span style="color: black;"><span style=<span class="string" style="color: red;">&#8220;font-family: &#8216;Comic Sans MS&#8217;; font-size: 18px;&#8221;</span>><span class="keyword" style="font-weight: bold; color: blue;">package</span> org.yanzi.testhorizontallistview; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> org.yanzi.ui.HorizontalListView; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> org.yanzi.ui.HorizontalListViewAdapter; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.app.Activity; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.os.Bundle; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.Menu; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.View; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.AdapterView; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.AdapterView.OnItemClickListener; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.ImageView; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">class</span> MainActivity <span class="keyword" style="font-weight: bold; color: blue;">extends</span> Activity { </span> - <span style="color: black;"> HorizontalListView hListView; </span> - <span style="color: black;"> HorizontalListViewAdapter hListViewAdapter; </span> - <span style="color: black;"> ImageView previewImg; </span> - <span style="color: black;"> View olderSelectView = <span class="keyword" style="font-weight: bold; color: blue;">null</span>; </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">protected</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> onCreate(Bundle savedInstanceState) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">super</span>.onCreate(savedInstanceState); </span> - <span style="color: black;"> setContentView(R.layout.activity_main); </span> - <span style="color: black;"> initUI(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> onCreateOptionsMenu(Menu menu) { </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// Inflate the menu; this adds items to the action bar if it is present.</span> </span> - <span style="color: black;"> getMenuInflater().inflate(R.menu.main, menu); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> <span class="keyword" style="font-weight: bold; color: blue;">true</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> initUI(){ </span> - <span style="color: black;"> hListView = (HorizontalListView)findViewById(R.id.horizon_listview); </span> - <span style="color: black;"> previewImg = (ImageView)findViewById(R.id.image_preview); </span> - <span style="color: black;"> String[] titles = {<span class="string" style="color: red;">&#8220;怀师&#8221;</span>, <span class="string" style="color: red;">&#8220;南怀瑾军校&#8221;</span>, <span class="string" style="color: red;">&#8220;闭关&#8221;</span>, <span class="string" style="color: red;">&#8220;南怀瑾&#8221;</span>, <span class="string" style="color: red;">&#8220;南公庄严照&#8221;</span>, <span class="string" style="color: red;">&#8220;怀师法相&#8221;</span>}; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">final</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span>[] ids = {R.drawable.nanhuaijin_miss, R.drawable.nanhuaijin_school, </span> - <span style="color: black;"> R.drawable.nanhuaijin_biguan, R.drawable.nanhuaijin, </span> - <span style="color: black;"> R.drawable.nanhuaijin_zhuangyan, R.drawable.nanhuaijin_faxiang}; </span> - <span style="color: black;"> hListViewAdapter = <span class="keyword" style="font-weight: bold; color: blue;">new</span> HorizontalListViewAdapter(getApplicationContext(),titles,ids); </span> - <span style="color: black;"> hListView.setAdapter(hListViewAdapter); </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// hListView.setOnItemSelectedListener(new OnItemSelectedListener() {</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">//</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// @Override</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// public void onItemSelected(AdapterView<?> parent, View view,</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// int position, long id) {</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// // TODO Auto-generated method stub</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// if(olderSelected != null){</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// olderSelected.setSelected(false); //上一个选中的View恢复原背景</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// }</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// olderSelected = view;</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// view.setSelected(true);</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// }</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">//</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// @Override</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// public void onNothingSelected(AdapterView<?> parent) {</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// // TODO Auto-generated method stub</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// </span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// }</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// });</span> </span> - <span style="color: black;"> hListView.setOnItemClickListener(<span class="keyword" style="font-weight: bold; color: blue;">new</span> OnItemClickListener() { </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> onItemClick(AdapterView<?> parent, View view, </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> position, <span class="keyword" style="font-weight: bold; color: blue;">long</span> id) { </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// TODO Auto-generated method stub</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// if(olderSelectView == null){</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// olderSelectView = view;</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// }else{</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// olderSelectView.setSelected(false);</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// olderSelectView = null;</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// }</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// olderSelectView = view;</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// view.setSelected(true);</span> </span> - <span style="color: black;"> previewImg.setImageResource(ids[position]); </span> - <span style="color: black;"> hListViewAdapter.setSelectIndex(position); </span> - <span style="color: black;"> hListViewAdapter.notifyDataSetChanged(); </span> - <span style="color: black;"> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> }); </span> - <span style="color: black;"> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;">} </span> - <span style="color: black;"></span> </span> HorizontalListView.java 这就是自定义的横向listview **[java]** [view plain](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[copy](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[print](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[?](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/237690)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/237690/fork) <div> </div> </div> </div> - <span style="color: black;"><span style=<span class="string" style="color: red;">&#8220;font-family: &#8216;Comic Sans MS&#8217;; font-size: 18px;&#8221;</span>><span class="keyword" style="font-weight: bold; color: blue;">package</span> org.yanzi.ui; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">/*</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * HorizontalListView.java v1.5</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> *</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * </span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * The MIT License</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * Copyright (c) 2011 Paul Soucy (paul@dev-smart.com)</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * </span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * Permission is hereby granted, free of charge, to any person obtaining a copy</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * of this software and associated documentation files (the &#8220;Software&#8221;), to deal</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * in the Software without restriction, including without limitation the rights</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * copies of the Software, and to permit persons to whom the Software is</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * furnished to do so, subject to the following conditions:</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * </span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * The above copyright notice and this permission notice shall be included in</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * all copies or substantial portions of the Software.</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * </span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * THE SOFTWARE IS PROVIDED &#8220;AS IS&#8221;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * THE SOFTWARE.</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> *</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> */</span> </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> java.util.LinkedList; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> java.util.Queue; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.content.Context; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.database.DataSetObserver; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.graphics.Rect; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.util.AttributeSet; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.GestureDetector; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.GestureDetector.OnGestureListener; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.MotionEvent; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.View; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.AdapterView; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.ListAdapter; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.Scroller; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">class</span> HorizontalListView <span class="keyword" style="font-weight: bold; color: blue;">extends</span> AdapterView<ListAdapter> { </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> mAlwaysOverrideTouch = <span class="keyword" style="font-weight: bold; color: blue;">true</span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">protected</span> ListAdapter mAdapter; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> mLeftViewIndex = &#8211;<span class="number" style="color: #c00000;">1</span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> mRightViewIndex = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">protected</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> mCurrentX; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">protected</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> mNextX; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> mMaxX = Integer.MAX_VALUE; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> mDisplayOffset = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">protected</span> Scroller mScroller; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> GestureDetector mGesture; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> Queue<View> mRemovedViewQueue = <span class="keyword" style="font-weight: bold; color: blue;">new</span> LinkedList<View>(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> OnItemSelectedListener mOnItemSelected; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> OnItemClickListener mOnItemClicked; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> OnItemLongClickListener mOnItemLongClicked; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> mDataChanged = <span class="keyword" style="font-weight: bold; color: blue;">false</span>; </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> HorizontalListView(Context context, AttributeSet attrs) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">super</span>(context, attrs); </span> - <span style="color: black;"> initView(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">synchronized</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> initView() { </span> - <span style="color: black;"> mLeftViewIndex = &#8211;<span class="number" style="color: #c00000;">1</span>; </span> - <span style="color: black;"> mRightViewIndex = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> mDisplayOffset = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> mCurrentX = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> mNextX = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> mMaxX = Integer.MAX_VALUE; </span> - <span style="color: black;"> mScroller = <span class="keyword" style="font-weight: bold; color: blue;">new</span> Scroller(getContext()); </span> - <span style="color: black;"> mGesture = <span class="keyword" style="font-weight: bold; color: blue;">new</span> GestureDetector(getContext(), mOnGesture); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) { </span> - <span style="color: black;"> mOnItemSelected = listener; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> setOnItemClickListener(AdapterView.OnItemClickListener listener){ </span> - <span style="color: black;"> mOnItemClicked = listener; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) { </span> - <span style="color: black;"> mOnItemLongClicked = listener; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> DataSetObserver mDataObserver = <span class="keyword" style="font-weight: bold; color: blue;">new</span> DataSetObserver() { </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> onChanged() { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">synchronized</span>(HorizontalListView.<span class="keyword" style="font-weight: bold; color: blue;">this</span>){ </span> - <span style="color: black;"> mDataChanged = <span class="keyword" style="font-weight: bold; color: blue;">true</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> invalidate(); </span> - <span style="color: black;"> requestLayout(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> onInvalidated() { </span> - <span style="color: black;"> reset(); </span> - <span style="color: black;"> invalidate(); </span> - <span style="color: black;"> requestLayout(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> }; </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> ListAdapter getAdapter() { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> mAdapter; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> View getSelectedView() { </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">//TODO: implement</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> <span class="keyword" style="font-weight: bold; color: blue;">null</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> setAdapter(ListAdapter adapter) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mAdapter != <span class="keyword" style="font-weight: bold; color: blue;">null</span>) { </span> - <span style="color: black;"> mAdapter.unregisterDataSetObserver(mDataObserver); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> mAdapter = adapter; </span> - <span style="color: black;"> mAdapter.registerDataSetObserver(mDataObserver); </span> - <span style="color: black;"> reset(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">synchronized</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> reset(){ </span> - <span style="color: black;"> initView(); </span> - <span style="color: black;"> removeAllViewsInLayout(); </span> - <span style="color: black;"> requestLayout(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> setSelection(<span class="keyword" style="font-weight: bold; color: blue;">int</span> position) { </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">//TODO: implement</span> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> addAndMeasureChild(<span class="keyword" style="font-weight: bold; color: blue;">final</span> View child, <span class="keyword" style="font-weight: bold; color: blue;">int</span> viewPos) { </span> - <span style="color: black;"> LayoutParams params = child.getLayoutParams(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(params == <span class="keyword" style="font-weight: bold; color: blue;">null</span>) { </span> - <span style="color: black;"> params = <span class="keyword" style="font-weight: bold; color: blue;">new</span> LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> addViewInLayout(child, viewPos, params, <span class="keyword" style="font-weight: bold; color: blue;">true</span>); </span> - <span style="color: black;"> child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), </span> - <span style="color: black;"> MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">protected</span> <span class="keyword" style="font-weight: bold; color: blue;">synchronized</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> onLayout(<span class="keyword" style="font-weight: bold; color: blue;">boolean</span> changed, <span class="keyword" style="font-weight: bold; color: blue;">int</span> left, <span class="keyword" style="font-weight: bold; color: blue;">int</span> top, <span class="keyword" style="font-weight: bold; color: blue;">int</span> right, <span class="keyword" style="font-weight: bold; color: blue;">int</span> bottom) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">super</span>.onLayout(changed, left, top, right, bottom); </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mAdapter == <span class="keyword" style="font-weight: bold; color: blue;">null</span>){ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mDataChanged){ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> oldCurrentX = mCurrentX; </span> - <span style="color: black;"> initView(); </span> - <span style="color: black;"> removeAllViewsInLayout(); </span> - <span style="color: black;"> mNextX = oldCurrentX; </span> - <span style="color: black;"> mDataChanged = <span class="keyword" style="font-weight: bold; color: blue;">false</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mScroller.computeScrollOffset()){ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> scrollx = mScroller.getCurrX(); </span> - <span style="color: black;"> mNextX = scrollx; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mNextX <= <span class="number" style="color: #c00000;"></span>){ </span> - <span style="color: black;"> mNextX = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> mScroller.forceFinished(<span class="keyword" style="font-weight: bold; color: blue;">true</span>); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mNextX >= mMaxX) { </span> - <span style="color: black;"> mNextX = mMaxX; </span> - <span style="color: black;"> mScroller.forceFinished(<span class="keyword" style="font-weight: bold; color: blue;">true</span>); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> dx = mCurrentX &#8211; mNextX; </span> - <span style="color: black;"> </span> - <span style="color: black;"> removeNonVisibleItems(dx); </span> - <span style="color: black;"> fillList(dx); </span> - <span style="color: black;"> positionItems(dx); </span> - <span style="color: black;"> </span> - <span style="color: black;"> mCurrentX = mNextX; </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(!mScroller.isFinished()){ </span> - <span style="color: black;"> post(<span class="keyword" style="font-weight: bold; color: blue;">new</span> Runnable(){ </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> run() { </span> - <span style="color: black;"> requestLayout(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> }); </span> - <span style="color: black;"> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> fillList(<span class="keyword" style="font-weight: bold; color: blue;">final</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> dx) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> edge = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> View child = getChildAt(getChildCount()-<span class="number" style="color: #c00000;">1</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(child != <span class="keyword" style="font-weight: bold; color: blue;">null</span>) { </span> - <span style="color: black;"> edge = child.getRight(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> fillListRight(edge, dx); </span> - <span style="color: black;"> </span> - <span style="color: black;"> edge = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> child = getChildAt(<span class="number" style="color: #c00000;"></span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(child != <span class="keyword" style="font-weight: bold; color: blue;">null</span>) { </span> - <span style="color: black;"> edge = child.getLeft(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> fillListLeft(edge, dx); </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> fillListRight(<span class="keyword" style="font-weight: bold; color: blue;">int</span> rightEdge, <span class="keyword" style="font-weight: bold; color: blue;">final</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> dx) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">while</span>(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) { </span> - <span style="color: black;"> </span> - <span style="color: black;"> View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), <span class="keyword" style="font-weight: bold; color: blue;">this</span>); </span> - <span style="color: black;"> addAndMeasureChild(child, &#8211;<span class="number" style="color: #c00000;">1</span>); </span> - <span style="color: black;"> rightEdge += child.getMeasuredWidth(); </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mRightViewIndex == mAdapter.getCount()-<span class="number" style="color: #c00000;">1</span>) { </span> - <span style="color: black;"> mMaxX = mCurrentX + rightEdge &#8211; getWidth(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span> (mMaxX < <span class="number" style="color: #c00000;"></span>) { </span> - <span style="color: black;"> mMaxX = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> mRightViewIndex++; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> fillListLeft(<span class="keyword" style="font-weight: bold; color: blue;">int</span> leftEdge, <span class="keyword" style="font-weight: bold; color: blue;">final</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> dx) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">while</span>(leftEdge + dx > <span class="number" style="color: #c00000;"></span> && mLeftViewIndex >= <span class="number" style="color: #c00000;"></span>) { </span> - <span style="color: black;"> View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), <span class="keyword" style="font-weight: bold; color: blue;">this</span>); </span> - <span style="color: black;"> addAndMeasureChild(child, <span class="number" style="color: #c00000;"></span>); </span> - <span style="color: black;"> leftEdge -= child.getMeasuredWidth(); </span> - <span style="color: black;"> mLeftViewIndex&#8211;; </span> - <span style="color: black;"> mDisplayOffset -= child.getMeasuredWidth(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> removeNonVisibleItems(<span class="keyword" style="font-weight: bold; color: blue;">final</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> dx) { </span> - <span style="color: black;"> View child = getChildAt(<span class="number" style="color: #c00000;"></span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">while</span>(child != <span class="keyword" style="font-weight: bold; color: blue;">null</span> && child.getRight() + dx <= <span class="number" style="color: #c00000;"></span>) { </span> - <span style="color: black;"> mDisplayOffset += child.getMeasuredWidth(); </span> - <span style="color: black;"> mRemovedViewQueue.offer(child); </span> - <span style="color: black;"> removeViewInLayout(child); </span> - <span style="color: black;"> mLeftViewIndex++; </span> - <span style="color: black;"> child = getChildAt(<span class="number" style="color: #c00000;"></span>); </span> - <span style="color: black;"> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> child = getChildAt(getChildCount()-<span class="number" style="color: #c00000;">1</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">while</span>(child != <span class="keyword" style="font-weight: bold; color: blue;">null</span> && child.getLeft() + dx >= getWidth()) { </span> - <span style="color: black;"> mRemovedViewQueue.offer(child); </span> - <span style="color: black;"> removeViewInLayout(child); </span> - <span style="color: black;"> mRightViewIndex&#8211;; </span> - <span style="color: black;"> child = getChildAt(getChildCount()-<span class="number" style="color: #c00000;">1</span>); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> positionItems(<span class="keyword" style="font-weight: bold; color: blue;">final</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> dx) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(getChildCount() > <span class="number" style="color: #c00000;"></span>){ </span> - <span style="color: black;"> mDisplayOffset += dx; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> left = mDisplayOffset; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">for</span>(<span class="keyword" style="font-weight: bold; color: blue;">int</span> i=<span class="number" style="color: #c00000;"></span>;i<getChildCount();i++){ </span> - <span style="color: black;"> View child = getChildAt(i); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> childWidth = child.getMeasuredWidth(); </span> - <span style="color: black;"> child.layout(left, <span class="number" style="color: #c00000;"></span>, left + childWidth, child.getMeasuredHeight()); </span> - <span style="color: black;"> left += childWidth + child.getPaddingRight(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">synchronized</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> scrollTo(<span class="keyword" style="font-weight: bold; color: blue;">int</span> x) { </span> - <span style="color: black;"> mScroller.startScroll(mNextX, <span class="number" style="color: #c00000;"></span>, x &#8211; mNextX, <span class="number" style="color: #c00000;"></span>); </span> - <span style="color: black;"> requestLayout(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> dispatchTouchEvent(MotionEvent ev) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> handled = <span class="keyword" style="font-weight: bold; color: blue;">super</span>.dispatchTouchEvent(ev); </span> - <span style="color: black;"> handled |= mGesture.onTouchEvent(ev); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> handled; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">protected</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> onFling(MotionEvent e1, MotionEvent e2, <span class="keyword" style="font-weight: bold; color: blue;">float</span> velocityX, </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">float</span> velocityY) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">synchronized</span>(HorizontalListView.<span class="keyword" style="font-weight: bold; color: blue;">this</span>){ </span> - <span style="color: black;"> mScroller.fling(mNextX, <span class="number" style="color: #c00000;"></span>, (<span class="keyword" style="font-weight: bold; color: blue;">int</span>)-velocityX, <span class="number" style="color: #c00000;"></span>, <span class="number" style="color: #c00000;"></span>, mMaxX, <span class="number" style="color: #c00000;"></span>, <span class="number" style="color: #c00000;"></span>); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> requestLayout(); </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> <span class="keyword" style="font-weight: bold; color: blue;">true</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">protected</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> onDown(MotionEvent e) { </span> - <span style="color: black;"> mScroller.forceFinished(<span class="keyword" style="font-weight: bold; color: blue;">true</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> <span class="keyword" style="font-weight: bold; color: blue;">true</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> OnGestureListener mOnGesture = <span class="keyword" style="font-weight: bold; color: blue;">new</span> GestureDetector.SimpleOnGestureListener() { </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> onDown(MotionEvent e) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> HorizontalListView.<span class="keyword" style="font-weight: bold; color: blue;">this</span>.onDown(e); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> onFling(MotionEvent e1, MotionEvent e2, <span class="keyword" style="font-weight: bold; color: blue;">float</span> velocityX, </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">float</span> velocityY) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> HorizontalListView.<span class="keyword" style="font-weight: bold; color: blue;">this</span>.onFling(e1, e2, velocityX, velocityY); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> onScroll(MotionEvent e1, MotionEvent e2, </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">float</span> distanceX, <span class="keyword" style="font-weight: bold; color: blue;">float</span> distanceY) { </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">synchronized</span>(HorizontalListView.<span class="keyword" style="font-weight: bold; color: blue;">this</span>){ </span> - <span style="color: black;"> mNextX += (<span class="keyword" style="font-weight: bold; color: blue;">int</span>)distanceX; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> requestLayout(); </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> <span class="keyword" style="font-weight: bold; color: blue;">true</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> onSingleTapConfirmed(MotionEvent e) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">for</span>(<span class="keyword" style="font-weight: bold; color: blue;">int</span> i=<span class="number" style="color: #c00000;"></span>;i<getChildCount();i++){ </span> - <span style="color: black;"> View child = getChildAt(i); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span> (isEventWithinView(e, child)) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mOnItemClicked != <span class="keyword" style="font-weight: bold; color: blue;">null</span>){ </span> - <span style="color: black;"> mOnItemClicked.onItemClick(HorizontalListView.<span class="keyword" style="font-weight: bold; color: blue;">this</span>, child, mLeftViewIndex + <span class="number" style="color: #c00000;">1</span> + i, mAdapter.getItemId( mLeftViewIndex + <span class="number" style="color: #c00000;">1</span> + i )); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(mOnItemSelected != <span class="keyword" style="font-weight: bold; color: blue;">null</span>){ </span> - <span style="color: black;"> mOnItemSelected.onItemSelected(HorizontalListView.<span class="keyword" style="font-weight: bold; color: blue;">this</span>, child, mLeftViewIndex + <span class="number" style="color: #c00000;">1</span> + i, mAdapter.getItemId( mLeftViewIndex + <span class="number" style="color: #c00000;">1</span> + i )); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">break</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> <span class="keyword" style="font-weight: bold; color: blue;">true</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> onLongPress(MotionEvent e) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> childCount = getChildCount(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">for</span> (<span class="keyword" style="font-weight: bold; color: blue;">int</span> i = <span class="number" style="color: #c00000;"></span>; i < childCount; i++) { </span> - <span style="color: black;"> View child = getChildAt(i); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span> (isEventWithinView(e, child)) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span> (mOnItemLongClicked != <span class="keyword" style="font-weight: bold; color: blue;">null</span>) { </span> - <span style="color: black;"> mOnItemLongClicked.onItemLongClick(HorizontalListView.<span class="keyword" style="font-weight: bold; color: blue;">this</span>, child, mLeftViewIndex + <span class="number" style="color: #c00000;">1</span> + i, mAdapter.getItemId(mLeftViewIndex + <span class="number" style="color: #c00000;">1</span> + i)); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">break</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">boolean</span> isEventWithinView(MotionEvent e, View child) { </span> - <span style="color: black;"> Rect viewRect = <span class="keyword" style="font-weight: bold; color: blue;">new</span> Rect(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span>[] childPosition = <span class="keyword" style="font-weight: bold; color: blue;">new</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span>[<span class="number" style="color: #c00000;">2</span>]; </span> - <span style="color: black;"> child.getLocationOnScreen(childPosition); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> left = childPosition[<span class="number" style="color: #c00000;"></span>]; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> right = left + child.getWidth(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> top = childPosition[<span class="number" style="color: #c00000;">1</span>]; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> bottom = top + child.getHeight(); </span> - <span style="color: black;"> viewRect.set(left, top, right, bottom); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> viewRect.contains((<span class="keyword" style="font-weight: bold; color: blue;">int</span>) e.getRawX(), (<span class="keyword" style="font-weight: bold; color: blue;">int</span>) e.getRawY()); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> }; </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;">} </span> - <span style="color: black;"></span> </span> HorizontalListViewAdapter.java 横向listview的适配器,我将他单独写到一个java文件里。 **[java]** [view plain](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[copy](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[print](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[?](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/237690)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/237690/fork) <div> </div> </div> </div> - <span style="color: black;"><span style=<span class="string" style="color: red;">&#8220;font-family: &#8216;Comic Sans MS&#8217;; font-size: 18px;&#8221;</span>><span class="keyword" style="font-weight: bold; color: blue;">package</span> org.yanzi.ui; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> org.yanzi.testhorizontallistview.R; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> org.yanzi.util.BitmapUtil; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.content.Context; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.graphics.Bitmap; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.graphics.drawable.Drawable; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.media.ThumbnailUtils; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.LayoutInflater; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.View; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.view.ViewGroup; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.BaseAdapter; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.ImageView; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">import</span> android.widget.TextView; </span> - <span style="color: black;"> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">class</span> HorizontalListViewAdapter <span class="keyword" style="font-weight: bold; color: blue;">extends</span> BaseAdapter{ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span>[] mIconIDs; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> String[] mTitles; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> Context mContext; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> LayoutInflater mInflater; </span> - <span style="color: black;"> Bitmap iconBitmap; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> selectIndex = &#8211;<span class="number" style="color: #c00000;">1</span>; </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> HorizontalListViewAdapter(Context context, String[] titles, <span class="keyword" style="font-weight: bold; color: blue;">int</span>[] ids){ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">this</span>.mContext = context; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">this</span>.mIconIDs = ids; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">this</span>.mTitles = titles; </span> - <span style="color: black;"> mInflater=(LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);<span class="comment" style="color: #008200;">//LayoutInflater.from(mContext);</span> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">int</span> getCount() { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> mIconIDs.length; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> Object getItem(<span class="keyword" style="font-weight: bold; color: blue;">int</span> position) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> position; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">long</span> getItemId(<span class="keyword" style="font-weight: bold; color: blue;">int</span> position) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> position; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> View getView(<span class="keyword" style="font-weight: bold; color: blue;">int</span> position, View convertView, ViewGroup parent) { </span> - <span style="color: black;"> </span> - <span style="color: black;"> ViewHolder holder; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(convertView==<span class="keyword" style="font-weight: bold; color: blue;">null</span>){ </span> - <span style="color: black;"> holder = <span class="keyword" style="font-weight: bold; color: blue;">new</span> ViewHolder(); </span> - <span style="color: black;"> convertView = mInflater.inflate(R.layout.horizontal_list_item, <span class="keyword" style="font-weight: bold; color: blue;">null</span>); </span> - <span style="color: black;"> holder.mImage=(ImageView)convertView.findViewById(R.id.img_list_item); </span> - <span style="color: black;"> holder.mTitle=(TextView)convertView.findViewById(R.id.text_list_item); </span> - <span style="color: black;"> convertView.setTag(holder); </span> - <span style="color: black;"> }<span class="keyword" style="font-weight: bold; color: blue;">else</span>{ </span> - <span style="color: black;"> holder=(ViewHolder)convertView.getTag(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">if</span>(position == selectIndex){ </span> - <span style="color: black;"> convertView.setSelected(<span class="keyword" style="font-weight: bold; color: blue;">true</span>); </span> - <span style="color: black;"> }<span class="keyword" style="font-weight: bold; color: blue;">else</span>{ </span> - <span style="color: black;"> convertView.setSelected(<span class="keyword" style="font-weight: bold; color: blue;">false</span>); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> holder.mTitle.setText(mTitles[position]); </span> - <span style="color: black;"> iconBitmap = getPropThumnail(mIconIDs[position]); </span> - <span style="color: black;"> holder.mImage.setImageBitmap(iconBitmap); </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> convertView; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> <span class="keyword" style="font-weight: bold; color: blue;">static</span> <span class="keyword" style="font-weight: bold; color: blue;">class</span> ViewHolder { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> TextView mTitle ; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> ImageView mImage; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">private</span> Bitmap getPropThumnail(<span class="keyword" style="font-weight: bold; color: blue;">int</span> id){ </span> - <span style="color: black;"> Drawable d = mContext.getResources().getDrawable(id); </span> - <span style="color: black;"> Bitmap b = BitmapUtil.drawableToBitmap(d); </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// Bitmap bb = BitmapUtil.getRoundedCornerBitmap(b, 100);</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> w = mContext.getResources().getDimensionPixelOffset(R.dimen.thumnail_default_width); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">int</span> h = mContext.getResources().getDimensionPixelSize(R.dimen.thumnail_default_height); </span> - <span style="color: black;"> </span> - <span style="color: black;"> Bitmap thumBitmap = ThumbnailUtils.extractThumbnail(b, w, h); </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">return</span> thumBitmap; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: blue;">public</span> <span class="keyword" style="font-weight: bold; color: blue;">void</span> setSelectIndex(<span class="keyword" style="font-weight: bold; color: blue;">int</span> i){ </span> - <span style="color: black;"> selectIndex = i; </span> - <span style="color: black;"> } </span> - <span style="color: black;">}</span> </span> 下面是效果图: ![](http://img.blog.csdn.net/20140315182924656?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 下图是一个item被选定后,另一个item获得了焦点: ![](http://img.blog.csdn.net/20140315183047562?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 下面是横向时的截图: ![](http://img.blog.csdn.net/20140315183137906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 要点如下: 1、可以说这个HorizontalListView是完美的,但美中不足的并不是其他人说的不能点击、晃动、加载不全的问题,而是这个横向Listview的高度,如果你设成wrap_cotent那么将会占据整个屏幕,**即使你将它适配器里的view的高度限制死,限制成很小,这个HorizontalListView的高度依然是全屏**。本文代码里,我把图片缩略图弄成100dip,所以把这个HorizontalListView的高度设为了150dip。 2、在适配器里,我填充了一个图片,下面是文字。为了能让浏览图片时item有反应,搞了一个selector,它的用法详见[这里](http://blog.csdn.net/shakespeare001/article/details/7788400). 但一开始在点击时完全没有反应,参考这里: [http://blog.csdn.net/ljz2009y/article/details/18820071](http://blog.csdn.net/ljz2009y/article/details/18820071) 为此我的selector如下: <?xml version=”1.0″ encoding=”utf-8″?> 将自然状态下的背景放到了最后,但点击浏览时依然没有作用。**其实最根本原因是在布局文件里horizontal_list_item.xml要让这个布局能够clickable,即:android:clickable=”true”** 3、上一步完成了,还需要点击即select一个item时,让它变色并且保持住,然后点击另外一个item时,让之前得item恢复默认背景。为了实现这个问题,我曾作如下尝试: **[java]** [view plain](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[copy](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[print](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[?](http://blog.csdn.net/yanzi1225627/article/details/21294553#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/237690)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/237690/fork) <div> </div> </div> </div> - <span style="color: black;"><span style=<span class="string" style="color: red;">&#8220;font-family: &#8216;Comic Sans MS&#8217;; font-size: 18px;&#8221;</span>><span class="comment" style="color: #008200;">// if(olderSelectView == null){</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// olderSelectView = view;</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// }else{</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// olderSelectView.setSelected(false);</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// olderSelectView = null;</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// }</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// olderSelectView = view;</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;">// view.setSelected(true);</span></span> </span> 即在click监听里,保存上一个选中的view。遗憾的是这种方法会造成item的选中状态造成混乱,比如第一个item选中了,同时第5个item也莫名其妙的被选中了。上述情况发生在滑动时,即一屏显示不完的情况下。当我横屏时,在所有的item都能一次性显示出来情况下,用上述方法么问题。后来我想到,这可以是适配器里的缓存机制造成的,**<span style="color: #ff0000;">最好不要再listview适配器外对item作修改,即便修改则一定要调适配器的: hListViewAdapter.notifyDataSetChanged();通知刷新view,毕竟适配器才是view的提供者</span>**。参考这位大大的文章:[http://longyi-java.iteye.com/blog/976067](http://longyi-java.iteye.com/blog/976067) 在适配器里加了一个接口保存选中的索引,然后再getView函数里进行判断。如果是选中的item,则将布局设为选中状态即可,horizontal_list_item.xml里的Linearlayout就会自动加载那个selector了。而无需像这个参考链接里对每个item的元素分别设置状态。</div> <div> 4、BitmapUtil是个工具类,负责将id转成一个bitmap,然后用android自带的ThumbnailUtils去提取缩略图。 </div> <div> 5、之所以horizontal_list_item布局里要设置padding是为了选中item时,整个item有种被圈住的感觉,而不是光下面一点变色。 </div> <div> 源码下载:[http://download.csdn.net/detail/yanzi1225627/7046295](http://download.csdn.net/detail/yanzi1225627/7046295)</div> <div> 欢迎Android爱好者加群 <div id="group_name" class="group_name usrInputFont"> <span class="qname" title="Android您问我讲-2">**Android您问我讲-2,**</span> </div> **群号:**<span id="group_number" class="group_number">**19241311,备注:yanzi**</span> </div> <div> </div> <div> &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;本文系原创,转载请注明作者:yanzi1225627 </div> <div> </div> <div> </div> <div> 源码下载:[http://download.csdn.net/detail/yanzi1225627/7046295](http://download.csdn.net/detail/yanzi1225627/7046295) </div> <div> 源码下载:[http://download.csdn.net/detail/yanzi1225627/7046295](http://download.csdn.net/detail/yanzi1225627/7046295) </div>

2014年6月27日 · 37 分钟 · 天边的星星