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

POSTED ON2014年6月27日

本文内容:

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<ListAdapter>构造的HorizontalListView,这是以上所有方法里本人认为最正统的方法,本文即基于此方法,参见:这里

下面看源码:

这是Activity的布局文件:activity_main.xml [html] view plain copy print ?

  1. <spanstyle=“font-family:‘ComicSansMS';font-size:18px;”><RelativeLayoutxmlns:android=“http://schemas.android.com/apk/res/android”
  2. xmlns:tools=“http://schemas.android.com/tools”
  3. android:layout_width=“match_parent”
  4. android:layout_height=“match_parent”
  5. android:paddingBottom=“@dimen/activity_vertical_margin”
  6. android:paddingLeft=“@dimen/activity_horizontal_margin”
  7. android:paddingRight=“@dimen/activity_horizontal_margin”
  8. android:paddingTop=“@dimen/activity_vertical_margin”
  9. tools:context=“.MainActivity”
  10. >
  11. <org.yanzi.ui.HorizontalListView
  12. android:id=“@+id/horizon_listview”
  13. android:layout_width=“match_parent”
  14. android:layout_height=“150dip”
  15. android:layout_alignParentTop=“true”
  16. >
  17. </org.yanzi.ui.HorizontalListView>
  18. <ImageView
  19. android:id=“@+id/image_preview”
  20. android:layout_width=“wrap_content”
  21. android:layout_height=“wrap_content”
  22. android:layout_below=“@id/horizon_listview”
  23. android:layout_centerInParent=“true”
  24. android:clickable=“true”
  25. android:background=“@drawable/selector_imageview_background”
  26. />
  27. <!–android:background=”@android:drawable/ic_menu_gallery”–>
  28. </RelativeLayout></span>
这是横向listview的每个item的布局,图片+文字,horizontal_list_item.xml [html] view plain copy print ?

  1. <spanstyle=“font-family:‘ComicSansMS';font-size:18px;”><?xmlversion=“1.0”encoding=“utf-8″?>
  2. <LinearLayoutxmlns:android=“http://schemas.android.com/apk/res/android”
  3. android:layout_width=“wrap_content”
  4. android:layout_height=“wrap_content”
  5. android:paddingLeft=“2dip”
  6. android:paddingRight=“2dip”
  7. android:paddingTop=“2dip”
  8. android:paddingBottom=“2dip”
  9. android:orientation=“vertical”
  10. android:gravity=“center”
  11. android:clickable=“true”
  12. android:background=“@drawable/selector_item_background”>
  13. <ImageView
  14. android:id=“@+id/img_list_item”
  15. android:layout_width=“wrap_content”
  16. android:layout_height=“wrap_content”/>
  17. <TextView
  18. android:id=“@+id/text_list_item”
  19. android:layout_width=“match_parent”
  20. android:layout_height=“wrap_content”
  21. android:gravity=“center”/>
  22. </LinearLayout>
  23. </span>

下面文件是selector_imageview_background.xml,这是大图片你点击浏览时背景发生变化的selector,没有啥实际作用。

[html] view plain copy print ?

  1. <spanstyle=“font-family:‘ComicSansMS';font-size:18px;”><?xmlversion=“1.0”encoding=“utf-8″?>
  2. <selectorxmlns:android=“http://schemas.android.com/apk/res/android”>
  3. <itemandroid:drawable=“@android:color/holo_green_light”android:state_pressed=“true”/>
  4. <itemandroid:drawable=“@android:color/holo_green_light”android:state_focused=“true”/>
  5. <itemandroid:drawable=“@drawable/image_background”></item>
  6. <!–android:drawable=”@android:color/transparent”–>
  7. </selector></span>

下面是每个item的selector,在focus和select时颜色会发生变化:selector_item_background.xml

[html] view plain copy print ?

  1. <spanstyle=“font-family:‘ComicSansMS';font-size:18px;”><?xmlversion=“1.0”encoding=“utf-8″?>
  2. <selectorxmlns:android=“http://schemas.android.com/apk/res/android”>
  3. <itemandroid:drawable=“@android:color/holo_red_light”android:state_selected=“true”/>
  4. <itemandroid:drawable=“@android:color/holo_green_dark”android:state_pressed=“true”/>
  5. <itemandroid:drawable=“@android:color/transparent”/>
  6. </selector></span>

主程序:MainActivity.java

[java] view plain copy print ?

  1. <spanstyle=“font-family:‘ComicSansMS';font-size:18px;”>packageorg.yanzi.testhorizontallistview;
  2. importorg.yanzi.ui.HorizontalListView;
  3. importorg.yanzi.ui.HorizontalListViewAdapter;
  4. importandroid.app.Activity;
  5. importandroid.os.Bundle;
  6. importandroid.view.Menu;
  7. importandroid.view.View;
  8. importandroid.widget.AdapterView;
  9. importandroid.widget.AdapterView.OnItemClickListener;
  10. importandroid.widget.ImageView;
  11. publicclassMainActivityextendsActivity{
  12. HorizontalListViewhListView;
  13. HorizontalListViewAdapterhListViewAdapter;
  14. ImageViewpreviewImg;
  15. ViewolderSelectView=null;
  16. @Override
  17. protectedvoidonCreate(BundlesavedInstanceState){
  18. super.onCreate(savedInstanceState);
  19. setContentView(R.layout.activity_main);
  20. initUI();
  21. }
  22. @Override
  23. publicbooleanonCreateOptionsMenu(Menumenu){
  24. //Inflatethemenu;thisaddsitemstotheactionbarifitispresent.
  25. getMenuInflater().inflate(R.menu.main,menu);
  26. returntrue;
  27. }
  28. publicvoidinitUI(){
  29. hListView=(HorizontalListView)findViewById(R.id.horizon_listview);
  30. previewImg=(ImageView)findViewById(R.id.image_preview);
  31. String[]titles={“怀师”,“南怀瑾军校”,“闭关”,“南怀瑾”,“南公庄严照”,“怀师法相”};
  32. finalint[]ids={R.drawable.nanhuaijin_miss,R.drawable.nanhuaijin_school,
  33. R.drawable.nanhuaijin_biguan,R.drawable.nanhuaijin,
  34. R.drawable.nanhuaijin_zhuangyan,R.drawable.nanhuaijin_faxiang};
  35. hListViewAdapter=newHorizontalListViewAdapter(getApplicationContext(),titles,ids);
  36. hListView.setAdapter(hListViewAdapter);
  37. //hListView.setOnItemSelectedListener(newOnItemSelectedListener(){
  38. //
  39. //@Override
  40. //publicvoidonItemSelected(AdapterView<?>parent,Viewview,
  41. //intposition,longid){
  42. ////TODOAuto-generatedmethodstub
  43. //if(olderSelected!=null){
  44. //olderSelected.setSelected(false);//上一个选中的View恢复原背景
  45. //}
  46. //olderSelected=view;
  47. //view.setSelected(true);
  48. //}
  49. //
  50. //@Override
  51. //publicvoidonNothingSelected(AdapterView<?>parent){
  52. ////TODOAuto-generatedmethodstub
  53. //
  54. //}
  55. //});
  56. hListView.setOnItemClickListener(newOnItemClickListener(){
  57. @Override
  58. publicvoidonItemClick(AdapterView<?>parent,Viewview,
  59. intposition,longid){
  60. //TODOAuto-generatedmethodstub
  61. //if(olderSelectView==null){
  62. //olderSelectView=view;
  63. //}else{
  64. //olderSelectView.setSelected(false);
  65. //olderSelectView=null;
  66. //}
  67. //olderSelectView=view;
  68. //view.setSelected(true);
  69. previewImg.setImageResource(ids[position]);
  70. hListViewAdapter.setSelectIndex(position);
  71. hListViewAdapter.notifyDataSetChanged();
  72. }
  73. });
  74. }
  75. }
  76. </span>

HorizontalListView.java 这就是自定义的横向listview

[java] view plain copy print ?

  1. <spanstyle=“font-family:‘ComicSansMS';font-size:18px;”>packageorg.yanzi.ui;
  2. /*
  3. *HorizontalListView.javav1.5
  4. *
  5. *
  6. *TheMITLicense
  7. *Copyright(c)2011PaulSoucy(paul@dev-smart.com)
  8. *
  9. *Permissionisherebygranted,freeofcharge,toanypersonobtainingacopy
  10. *ofthissoftwareandassociateddocumentationfiles(the“Software”),todeal
  11. *intheSoftwarewithoutrestriction,includingwithoutlimitationtherights
  12. *touse,copy,modify,merge,publish,distribute,sublicense,and/orsell
  13. *copiesoftheSoftware,andtopermitpersonstowhomtheSoftwareis
  14. *furnishedtodoso,subjecttothefollowingconditions:
  15. *
  16. *Theabovecopyrightnoticeandthispermissionnoticeshallbeincludedin
  17. *allcopiesorsubstantialportionsoftheSoftware.
  18. *
  19. *THESOFTWAREISPROVIDED“ASIS”,WITHOUTWARRANTYOFANYKIND,EXPRESSOR
  20. *IMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOFMERCHANTABILITY,
  21. *FITNESSFORAPARTICULARPURPOSEANDNONINFRINGEMENT.INNOEVENTSHALLTHE
  22. *AUTHORSORCOPYRIGHTHOLDERSBELIABLEFORANYCLAIM,DAMAGESOROTHER
  23. *LIABILITY,WHETHERINANACTIONOFCONTRACT,TORTOROTHERWISE,ARISINGFROM,
  24. *OUTOFORINCONNECTIONWITHTHESOFTWAREORTHEUSEOROTHERDEALINGSIN
  25. *THESOFTWARE.
  26. *
  27. */
  28. importjava.util.LinkedList;
  29. importjava.util.Queue;
  30. importandroid.content.Context;
  31. importandroid.database.DataSetObserver;
  32. importandroid.graphics.Rect;
  33. importandroid.util.AttributeSet;
  34. importandroid.view.GestureDetector;
  35. importandroid.view.GestureDetector.OnGestureListener;
  36. importandroid.view.MotionEvent;
  37. importandroid.view.View;
  38. importandroid.widget.AdapterView;
  39. importandroid.widget.ListAdapter;
  40. importandroid.widget.Scroller;
  41. publicclassHorizontalListViewextendsAdapterView<ListAdapter>{
  42. publicbooleanmAlwaysOverrideTouch=true;
  43. protectedListAdaptermAdapter;
  44. privateintmLeftViewIndex=-1;
  45. privateintmRightViewIndex=0;
  46. protectedintmCurrentX;
  47. protectedintmNextX;
  48. privateintmMaxX=Integer.MAX_VALUE;
  49. privateintmDisplayOffset=0;
  50. protectedScrollermScroller;
  51. privateGestureDetectormGesture;
  52. privateQueue<View>mRemovedViewQueue=newLinkedList<View>();
  53. privateOnItemSelectedListenermOnItemSelected;
  54. privateOnItemClickListenermOnItemClicked;
  55. privateOnItemLongClickListenermOnItemLongClicked;
  56. privatebooleanmDataChanged=false;
  57. publicHorizontalListView(Contextcontext,AttributeSetattrs){
  58. super(context,attrs);
  59. initView();
  60. }
  61. privatesynchronizedvoidinitView(){
  62. mLeftViewIndex=-1;
  63. mRightViewIndex=0;
  64. mDisplayOffset=0;
  65. mCurrentX=0;
  66. mNextX=0;
  67. mMaxX=Integer.MAX_VALUE;
  68. mScroller=newScroller(getContext());
  69. mGesture=newGestureDetector(getContext(),mOnGesture);
  70. }
  71. @Override
  72. publicvoidsetOnItemSelectedListener(AdapterView.OnItemSelectedListenerlistener){
  73. mOnItemSelected=listener;
  74. }
  75. @Override
  76. publicvoidsetOnItemClickListener(AdapterView.OnItemClickListenerlistener){
  77. mOnItemClicked=listener;
  78. }
  79. @Override
  80. publicvoidsetOnItemLongClickListener(AdapterView.OnItemLongClickListenerlistener){
  81. mOnItemLongClicked=listener;
  82. }
  83. privateDataSetObservermDataObserver=newDataSetObserver(){
  84. @Override
  85. publicvoidonChanged(){
  86. synchronized(HorizontalListView.this){
  87. mDataChanged=true;
  88. }
  89. invalidate();
  90. requestLayout();
  91. }
  92. @Override
  93. publicvoidonInvalidated(){
  94. reset();
  95. invalidate();
  96. requestLayout();
  97. }
  98. };
  99. @Override
  100. publicListAdaptergetAdapter(){
  101. returnmAdapter;
  102. }
  103. @Override
  104. publicViewgetSelectedView(){
  105. //TODO:implement
  106. returnnull;
  107. }
  108. @Override
  109. publicvoidsetAdapter(ListAdapteradapter){
  110. if(mAdapter!=null){
  111. mAdapter.unregisterDataSetObserver(mDataObserver);
  112. }
  113. mAdapter=adapter;
  114. mAdapter.registerDataSetObserver(mDataObserver);
  115. reset();
  116. }
  117. privatesynchronizedvoidreset(){
  118. initView();
  119. removeAllViewsInLayout();
  120. requestLayout();
  121. }
  122. @Override
  123. publicvoidsetSelection(intposition){
  124. //TODO:implement
  125. }
  126. privatevoidaddAndMeasureChild(finalViewchild,intviewPos){
  127. LayoutParamsparams=child.getLayoutParams();
  128. if(params==null){
  129. params=newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
  130. }
  131. addViewInLayout(child,viewPos,params,true);
  132. child.measure(MeasureSpec.makeMeasureSpec(getWidth(),MeasureSpec.AT_MOST),
  133. MeasureSpec.makeMeasureSpec(getHeight(),MeasureSpec.AT_MOST));
  134. }
  135. @Override
  136. protectedsynchronizedvoidonLayout(booleanchanged,intleft,inttop,intright,intbottom){
  137. super.onLayout(changed,left,top,right,bottom);
  138. if(mAdapter==null){
  139. return;
  140. }
  141. if(mDataChanged){
  142. intoldCurrentX=mCurrentX;
  143. initView();
  144. removeAllViewsInLayout();
  145. mNextX=oldCurrentX;
  146. mDataChanged=false;
  147. }
  148. if(mScroller.computeScrollOffset()){
  149. intscrollx=mScroller.getCurrX();
  150. mNextX=scrollx;
  151. }
  152. if(mNextX<=0){
  153. mNextX=0;
  154. mScroller.forceFinished(true);
  155. }
  156. if(mNextX>=mMaxX){
  157. mNextX=mMaxX;
  158. mScroller.forceFinished(true);
  159. }
  160. intdx=mCurrentX–mNextX;
  161. removeNonVisibleItems(dx);
  162. fillList(dx);
  163. positionItems(dx);
  164. mCurrentX=mNextX;
  165. if(!mScroller.isFinished()){
  166. post(newRunnable(){
  167. @Override
  168. publicvoidrun(){
  169. requestLayout();
  170. }
  171. });
  172. }
  173. }
  174. privatevoidfillList(finalintdx){
  175. intedge=0;
  176. Viewchild=getChildAt(getChildCount()-1);
  177. if(child!=null){
  178. edge=child.getRight();
  179. }
  180. fillListRight(edge,dx);
  181. edge=0;
  182. child=getChildAt(0);
  183. if(child!=null){
  184. edge=child.getLeft();
  185. }
  186. fillListLeft(edge,dx);
  187. }
  188. privatevoidfillListRight(intrightEdge,finalintdx){
  189. while(rightEdge+dx<getWidth()&&mRightViewIndex<mAdapter.getCount()){
  190. Viewchild=mAdapter.getView(mRightViewIndex,mRemovedViewQueue.poll(),this);
  191. addAndMeasureChild(child,-1);
  192. rightEdge+=child.getMeasuredWidth();
  193. if(mRightViewIndex==mAdapter.getCount()-1){
  194. mMaxX=mCurrentX+rightEdge–getWidth();
  195. }
  196. if(mMaxX<0){
  197. mMaxX=0;
  198. }
  199. mRightViewIndex++;
  200. }
  201. }
  202. privatevoidfillListLeft(intleftEdge,finalintdx){
  203. while(leftEdge+dx>0&&mLeftViewIndex>=0){
  204. Viewchild=mAdapter.getView(mLeftViewIndex,mRemovedViewQueue.poll(),this);
  205. addAndMeasureChild(child,0);
  206. leftEdge-=child.getMeasuredWidth();
  207. mLeftViewIndex–;
  208. mDisplayOffset-=child.getMeasuredWidth();
  209. }
  210. }
  211. privatevoidremoveNonVisibleItems(finalintdx){
  212. Viewchild=getChildAt(0);
  213. while(child!=null&&child.getRight()+dx<=0){
  214. mDisplayOffset+=child.getMeasuredWidth();
  215. mRemovedViewQueue.offer(child);
  216. removeViewInLayout(child);
  217. mLeftViewIndex++;
  218. child=getChildAt(0);
  219. }
  220. child=getChildAt(getChildCount()-1);
  221. while(child!=null&&child.getLeft()+dx>=getWidth()){
  222. mRemovedViewQueue.offer(child);
  223. removeViewInLayout(child);
  224. mRightViewIndex–;
  225. child=getChildAt(getChildCount()-1);
  226. }
  227. }
  228. privatevoidpositionItems(finalintdx){
  229. if(getChildCount()>0){
  230. mDisplayOffset+=dx;
  231. intleft=mDisplayOffset;
  232. for(inti=0;i<getChildCount();i++){
  233. Viewchild=getChildAt(i);
  234. intchildWidth=child.getMeasuredWidth();
  235. child.layout(left,0,left+childWidth,child.getMeasuredHeight());
  236. left+=childWidth+child.getPaddingRight();
  237. }
  238. }
  239. }
  240. publicsynchronizedvoidscrollTo(intx){
  241. mScroller.startScroll(mNextX,0,x–mNextX,0);
  242. requestLayout();
  243. }
  244. @Override
  245. publicbooleandispatchTouchEvent(MotionEventev){
  246. booleanhandled=super.dispatchTouchEvent(ev);
  247. handled|=mGesture.onTouchEvent(ev);
  248. returnhandled;
  249. }
  250. protectedbooleanonFling(MotionEvente1,MotionEvente2,floatvelocityX,
  251. floatvelocityY){
  252. synchronized(HorizontalListView.this){
  253. mScroller.fling(mNextX,0,(int)-velocityX,0,0,mMaxX,0,0);
  254. }
  255. requestLayout();
  256. returntrue;
  257. }
  258. protectedbooleanonDown(MotionEvente){
  259. mScroller.forceFinished(true);
  260. returntrue;
  261. }
  262. privateOnGestureListenermOnGesture=newGestureDetector.SimpleOnGestureListener(){
  263. @Override
  264. publicbooleanonDown(MotionEvente){
  265. returnHorizontalListView.this.onDown(e);
  266. }
  267. @Override
  268. publicbooleanonFling(MotionEvente1,MotionEvente2,floatvelocityX,
  269. floatvelocityY){
  270. returnHorizontalListView.this.onFling(e1,e2,velocityX,velocityY);
  271. }
  272. @Override
  273. publicbooleanonScroll(MotionEvente1,MotionEvente2,
  274. floatdistanceX,floatdistanceY){
  275. synchronized(HorizontalListView.this){
  276. mNextX+=(int)distanceX;
  277. }
  278. requestLayout();
  279. returntrue;
  280. }
  281. @Override
  282. publicbooleanonSingleTapConfirmed(MotionEvente){
  283. for(inti=0;i<getChildCount();i++){
  284. Viewchild=getChildAt(i);
  285. if(isEventWithinView(e,child)){
  286. if(mOnItemClicked!=null){
  287. mOnItemClicked.onItemClick(HorizontalListView.this,child,mLeftViewIndex+1+i,mAdapter.getItemId(mLeftViewIndex+1+i));
  288. }
  289. if(mOnItemSelected!=null){
  290. mOnItemSelected.onItemSelected(HorizontalListView.this,child,mLeftViewIndex+1+i,mAdapter.getItemId(mLeftViewIndex+1+i));
  291. }
  292. break;
  293. }
  294. }
  295. returntrue;
  296. }
  297. @Override
  298. publicvoidonLongPress(MotionEvente){
  299. intchildCount=getChildCount();
  300. for(inti=0;i<childCount;i++){
  301. Viewchild=getChildAt(i);
  302. if(isEventWithinView(e,child)){
  303. if(mOnItemLongClicked!=null){
  304. mOnItemLongClicked.onItemLongClick(HorizontalListView.this,child,mLeftViewIndex+1+i,mAdapter.getItemId(mLeftViewIndex+1+i));
  305. }
  306. break;
  307. }
  308. }
  309. }
  310. privatebooleanisEventWithinView(MotionEvente,Viewchild){
  311. RectviewRect=newRect();
  312. int[]childPosition=newint[2];
  313. child.getLocationOnScreen(childPosition);
  314. intleft=childPosition[0];
  315. intright=left+child.getWidth();
  316. inttop=childPosition[1];
  317. intbottom=top+child.getHeight();
  318. viewRect.set(left,top,right,bottom);
  319. returnviewRect.contains((int)e.getRawX(),(int)e.getRawY());
  320. }
  321. };
  322. }
  323. </span>

HorizontalListViewAdapter.java 横向listview的适配器,我将他单独写到一个java文件里。

[java] view plain copy print ?

  1. <spanstyle=“font-family:‘ComicSansMS';font-size:18px;”>packageorg.yanzi.ui;
  2. importorg.yanzi.testhorizontallistview.R;
  3. importorg.yanzi.util.BitmapUtil;
  4. importandroid.content.Context;
  5. importandroid.graphics.Bitmap;
  6. importandroid.graphics.drawable.Drawable;
  7. importandroid.media.ThumbnailUtils;
  8. importandroid.view.LayoutInflater;
  9. importandroid.view.View;
  10. importandroid.view.ViewGroup;
  11. importandroid.widget.BaseAdapter;
  12. importandroid.widget.ImageView;
  13. importandroid.widget.TextView;
  14. publicclassHorizontalListViewAdapterextendsBaseAdapter{
  15. privateint[]mIconIDs;
  16. privateString[]mTitles;
  17. privateContextmContext;
  18. privateLayoutInflatermInflater;
  19. BitmapiconBitmap;
  20. privateintselectIndex=-1;
  21. publicHorizontalListViewAdapter(Contextcontext,String[]titles,int[]ids){
  22. this.mContext=context;
  23. this.mIconIDs=ids;
  24. this.mTitles=titles;
  25. mInflater=(LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);//LayoutInflater.from(mContext);
  26. }
  27. @Override
  28. publicintgetCount(){
  29. returnmIconIDs.length;
  30. }
  31. @Override
  32. publicObjectgetItem(intposition){
  33. returnposition;
  34. }
  35. @Override
  36. publiclonggetItemId(intposition){
  37. returnposition;
  38. }
  39. @Override
  40. publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
  41. ViewHolderholder;
  42. if(convertView==null){
  43. holder=newViewHolder();
  44. convertView=mInflater.inflate(R.layout.horizontal_list_item,null);
  45. holder.mImage=(ImageView)convertView.findViewById(R.id.img_list_item);
  46. holder.mTitle=(TextView)convertView.findViewById(R.id.text_list_item);
  47. convertView.setTag(holder);
  48. }else{
  49. holder=(ViewHolder)convertView.getTag();
  50. }
  51. if(position==selectIndex){
  52. convertView.setSelected(true);
  53. }else{
  54. convertView.setSelected(false);
  55. }
  56. holder.mTitle.setText(mTitles[position]);
  57. iconBitmap=getPropThumnail(mIconIDs[position]);
  58. holder.mImage.setImageBitmap(iconBitmap);
  59. returnconvertView;
  60. }
  61. privatestaticclassViewHolder{
  62. privateTextViewmTitle;
  63. privateImageViewmImage;
  64. }
  65. privateBitmapgetPropThumnail(intid){
  66. Drawabled=mContext.getResources().getDrawable(id);
  67. Bitmapb=BitmapUtil.drawableToBitmap(d);
  68. //Bitmapbb=BitmapUtil.getRoundedCornerBitmap(b,100);
  69. intw=mContext.getResources().getDimensionPixelOffset(R.dimen.thumnail_default_width);
  70. inth=mContext.getResources().getDimensionPixelSize(R.dimen.thumnail_default_height);
  71. BitmapthumBitmap=ThumbnailUtils.extractThumbnail(b,w,h);
  72. returnthumBitmap;
  73. }
  74. publicvoidsetSelectIndex(inti){
  75. selectIndex=i;
  76. }
  77. }</span>

下面是效果图:

下图是一个item被选定后,另一个item获得了焦点: 下面是横向时的截图:

要点如下:

1、可以说这个HorizontalListView是完美的,但美中不足的并不是其他人说的不能点击、晃动、加载不全的问题,而是这个横向Listview的高度,如果你设成wrap_cotent那么将会占据整个屏幕, 即使你将它适配器里的view的高度限制死,限制成很小,这个HorizontalListView的高度依然是全屏。本文代码里,我把图片缩略图弄成100dip,所以把这个HorizontalListView的高度设为了150dip。 2、在适配器里,我填充了一个图片,下面是文字。为了能让浏览图片时item有反应,搞了一个selector,它的用法详见 这里. 但一开始在点击时完全没有反应,参考这里: http://blog.csdn.net/ljz2009y/article/details/18820071 为此我的selector如下: <?xml version=”1.0″ encoding=”utf-8″?>
<selector xmlns:android=”http://schemas.android.com/apk/res/android”>
<item android:drawable=”@android:color/holo_red_light” android:state_selected=”true”/>
<item android:drawable=”@android:color/holo_green_dark” android:state_pressed=”true”/>
<item android:drawable=”@android:color/transparent”/>
</selector> 将自然状态下的背景放到了最后,但点击浏览时依然没有作用。 其实最根本原因是在布局文件里horizontal_list_item.xml要让这个布局能够clickable,即:android:clickable=”true” 3、上一步完成了,还需要点击即select一个item时,让它变色并且保持住,然后点击另外一个item时,让之前得item恢复默认背景。为了实现这个问题,我曾作如下尝试: [java] view plain copy print ?

  1. <spanstyle=“font-family:‘ComicSansMS';font-size:18px;”>//if(olderSelectView==null){
  2. //olderSelectView=view;
  3. //}else{
  4. //olderSelectView.setSelected(false);
  5. //olderSelectView=null;
  6. //}
  7. //olderSelectView=view;
  8. //view.setSelected(true);</span>

即在click监听里,保存上一个选中的view。遗憾的是这种方法会造成item的选中状态造成混乱,比如第一个item选中了,同时第5个item也莫名其妙的被选中了。上述情况发生在滑动时,即一屏显示不完的情况下。当我横屏时,在所有的item都能一次性显示出来情况下,用上述方法么问题。后来我想到,这可以是适配器里的缓存机制造成的,最好不要再listview适配器外对item作修改,即便修改则一定要调适配器的: hListViewAdapter.notifyDataSetChanged();通知刷新view,毕竟适配器才是view的提供者。参考这位大大的文章:http://longyi-java.iteye.com/blog/976067在适配器里加了一个接口保存选中的索引,然后再getView函数里进行判断。如果是选中的item,则将布局设为选中状态即可,horizontal_list_item.xml里的Linearlayout就会自动加载那个selector了。而无需像这个参考链接里对每个item的元素分别设置状态。

4、BitmapUtil是个工具类,负责将id转成一个bitmap,然后用android自带的ThumbnailUtils去提取缩略图。 5、之所以horizontal_list_item布局里要设置padding是为了选中item时,整个item有种被圈住的感觉,而不是光下面一点变色。

源码下载:http://download.csdn.net/detail/yanzi1225627/7046295

更多相关文章

  1. Android中如何取消listview的点击效果
  2. Android(安卓)开发ListView适配器优化
  3. ListView中显示圆形图像
  4. Android常用UI组件 - ListView
  5. Android中的RecyclerView的使用(一)
  6. java/android 设计模式学习笔记(6)---适配器模式
  7. Android(安卓)学习
  8. Android简易实战教程--第四十六话《RecyclerView竖向和横向滚动
  9. Android新手入门2016(8)--ListView之ArrayAdapter

随机推荐

  1. Android基础之Android动画
  2. Android4.4 Telephony流程分析——联系人
  3. android 调试跟踪framework层代码
  4. Android(安卓)JNI代码
  5. Android数据手册:Android颜色码制表
  6. Android(安卓)EventBus实战 没听过你就ou
  7. Android(安卓)学习系列 - Fragment
  8. 设备管理器权限- Android
  9. Android(安卓)的 system property servic
  10. 探索Popupwindow-对话框风格的窗口