Android中的水平ListView?

是否有可能使ListView水平? 我已经完成了这个使用图库视图,但选定的项目自动进入屏幕的中心。 我不想在我点击的同一地点select的项目。 我如何解决这个问题? 我的想法是设置水平滚动ListView 。 分享你的想法?

按照Android文档RecyclerView是组织在列表视图中的项目和水平显示的新方法

优点:

  1. 由于使用RecyclerView Adapter, ViewHolder模式自动实现
  2. animation很容易执行
  3. 还有更多的function

有关RecyclerView更多信息:

  1. grokkingandroid.com
  2. antonioleiva.com

样品:

survivingwithandroid.com

只需添加下面的块,使ListView从垂直水平

代码段

 LinearLayoutManager layoutManager= new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL, false); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(layoutManager); 

保罗不打算修复他的图书馆的错误或接受用户的修复。 这就是为什么我build议另一个类似function的库:

https://github.com/sephiroth74/Horizo​​ntalVariableListView

更新 :2013年7月24日作者(sephiroth74)基于Android 4.2.2 ListView的代码发布了完全改写的版本。 我必须说,它没有所有的错误,以前的版本和伟大的工作!

@Paul答案链接到一个很好的解决scheme,但代码不允许使用项目子项上的onClickListeners(callback函数永远不会被调用)。 我一直在努力寻找一个解决scheme,我决定在这里发布你需要修改的代码(以防有人需要)。

而不是重写onTouchEvent dispatchTouchEvent覆盖。 使用相同的dispatchTouchEvent代码并删除方法(你可以在这里阅读http://developer.android.com/guide/topics/ui/ui-events.html#EventHandlers

 @Override public boolean onTouchEvent(MotionEvent event) { boolean handled = mGesture.onTouchEvent(event); return handled; } 

然后,添加下面的代码,它将决定从项目的子项中窃取事件,并将其提供给我们的onTouchEvent ,或让它们由它们处理。

 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch( ev.getActionMasked() ){ case MotionEvent.ACTION_DOWN: mInitialX = ev.getX(); mInitialY = ev.getY(); return false; case MotionEvent.ACTION_MOVE: float deltaX = Math.abs(ev.getX() - mInitialX); float deltaY = Math.abs(ev.getY() - mInitialY); return ( deltaX > 5 || deltaY > 5 ); default: return super.onInterceptTouchEvent(ev); } } 

最后,不要忘记在你的类中声明variables:

 private float mInitialX; private float mInitialY; 

这有点(很晚),但我发布这个以防万一以后有人来。

作为Android L预览的支持库有一个RecyclerView ,它完全符合你的需求。

现在,你只能通过L预览SDK获得它,你需要将你的minSdk设置为L 但是,您可以将所有必要的文件复制到您的项目中,并以这种方式使用它们,直到L正式出来。

您可以在这里下载预览文档。

警告:回收站视图的API可能会更改,并可能有错误。

更新

水平listview的源代码是:

 LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); RecyclerView myList = findViewById(R.id.my_recycler_view); myList.setLayoutManager(layoutManager); 

由于Google引入了Android支持库v7 21.0.0,您可以使用RecyclerView水平滚动项目。 RecyclerView小部件是ListView的更高级和灵活的版本。

要使用RecyclerView,只需添加依赖关系:

 com.android.support:recyclerview-v7:23.0.1 

这是一个示例:

 public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_activity); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(layoutManager); MyAdapter adapter = new MyAdapter(myDataset); recyclerView.setAdapter(adapter); } } 

有关RecyclerView的更多信息:

从这里下载jar文件

现在把它放到你的libs文件夹中,右键点击它并select'Add as library'

现在在main.xml中放这个代码

  <com.devsmart.android.ui.HorizontalListView android:id="@+id/hlistview" android:layout_width="fill_parent" android:layout_height="wrap_content" /> 

现在在Activity类,如果你想水平列表与图像,然后把这个代码

  HorizontalListView hListView = (HorizontalListView) findViewById(R.id.hlistview); hListView.setAdapter(new HAdapter(this)); private class HAdapter extends BaseAdapter { LayoutInflater inflater; public HAdapter(Context context) { inflater = LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return Const.template.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return position; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { HViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.listinflate, null); holder = new HViewHolder(); convertView.setTag(holder); } else { holder = (HViewHolder) convertView.getTag(); } holder.img = (ImageView) convertView.findViewById(R.id.image); holder.img.setImageResource(Const.template[position]); return convertView; } } class HViewHolder { ImageView img; } 

其实很简单 :简单地旋转列表视图放在它的一边

mlistView.setRotation(-90);

然后膨胀孩子,这应该在getView方法。 你旋转孩子站直:

  mylistViewchild.setRotation(90); 

编辑:如果你的ListView不适合旋转之后,将这个ListView放在这个RotateLayout里面,像这样:

  <com.github.rongi.rotate_layout.layout.RotateLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" app:angle="90"> <!-- Specify rotate angle here --> <ListView android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> </com.github.rongi.rotate_layout.layout.RotateLayout> 

我的解决scheme是简单地使用ViewPager小部件。 它不是作为Gallery中心locking的,并且具有用于回收视图(如ListView )的内置function。 无论何时处理水平滚动列表,您都可以在Google Play应用中看到类似的方法。

你只需要扩展PagerAdapter并在那里执行一些调整:

 public class MyPagerAdapter extends PagerAdapter { private Context mContext; public MyPagerAdapter(Context context) { this.mContext = context; } // As per docs, you may use views as key objects directly // if they aren't too complex @Override public Object instantiateItem(ViewGroup container, int position) { LayoutInflater inflater = LayoutInflater.from(mContext); View view = inflater.inflate(R.layout.item, null); container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public int getCount() { return 10; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } // Important: page takes all available width by default, // so let's override this method to fit 5 pages within single screen @Override public float getPageWidth(int position) { return 0.2f; } } 

结果是,你将有一个适配器水平滚动的小部件,就像这样: 在这里输入图像描述

您可以在支持库中使用RecyclerView。 RecyclerView是ListView的一个广义版本,支持:

  • 定位项目的布局pipe理器
  • 常用项目操作的默认animation

Android Recycler查看文档

我已经开发了一个逻辑来做到这一点,而不使用任何外部的水平滚动视图库,这里是我实现的水平视图,我已经在这里发布我的答案: https ://stackoverflow.com/a/33301582/5479863

我的JSON响应是这样的:

 {"searchInfo":{"status":"1","message":"Success","clist":[{"id":"1de57434-795e-49ac-0ca3-5614dacecbd4","name":"Theater","image_url":"http://52.25.198.71/miisecretory/category_images/movie.png"},{"id":"62fe1c92-2192-2ebb-7e92-5614dacad69b","name":"CNG","image_url":"http://52.25.198.71/miisecretory/category_images/cng.png"},{"id":"8060094c-df4f-5290-7983-5614dad31677","name":"Wine-shop","image_url":"http://52.25.198.71/miisecretory/category_images/beer.png"},{"id":"888a90c4-a6b0-c2e2-6b3c-561788e973f6","name":"Chemist","image_url":"http://52.25.198.71/miisecretory/category_images/chemist.png"},{"id":"a39b4ec1-943f-b800-a671-561789a57871","name":"Food","image_url":"http://52.25.198.71/miisecretory/category_images/food.png"},{"id":"c644cc53-2fce-8cbe-0715-5614da9c765f","name":"College","image_url":"http://52.25.198.71/miisecretory/category_images/college.png"},{"id":"c71e8757-072b-1bf4-5b25-5614d980ef15","name":"Hospital","image_url":"http://52.25.198.71/miisecretory/category_images/hospital.png"},{"id":"db835491-d1d2-5467-a1a1-5614d9963c94","name":"Petrol-Pumps","image_url":"http://52.25.198.71/miisecretory/category_images/petrol.png"},{"id":"f13100ca-4052-c0f4-863a-5614d9631afb","name":"ATM","image_url":"http://52.25.198.71/miisecretory/category_images/atm.png"}]}} 

布局文件:

  <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="5"> <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="4" /> <HorizontalScrollView android:id="@+id/horizontalScroll" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <LinearLayout android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="horizontal"> </LinearLayout> </HorizontalScrollView> </LinearLayout> 

类文件:

 LinearLayout linearLayout = (LinearLayout) findViewById(R.id.ll); for (int v = 0; v < collectionInfo.size(); v++) { /*---------------Creating frame layout----------------------*/ FrameLayout frameLayout = new FrameLayout(ActivityMap.this); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, getPixelsToDP(90)); layoutParams.rightMargin = getPixelsToDP(10); frameLayout.setLayoutParams(layoutParams); /*--------------end of frame layout----------------------------*/ /*---------------Creating image view----------------------*/ final ImageView imgView = new ImageView(ActivityMap.this); //create imageview dynamically LinearLayout.LayoutParams lpImage = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); imgView.setImageBitmap(collectionInfo.get(v).getCatImage()); imgView.setLayoutParams(lpImage); // setting ID to retrieve at later time (same as its position) imgView.setId(v); imgView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // getting id which is same as its position Log.i(TAG, "Clicked on " + collectionInfo.get(v.getId()).getCatName()); // getting selected category's data list new GetSelectedCategoryData().execute(collectionInfo.get(v.getId()).getCatID()); } }); /*--------------end of image view----------------------------*/ /*---------------Creating Text view----------------------*/ TextView textView = new TextView(ActivityMap.this);//create textview dynamically textView.setText(collectionInfo.get(v).getCatName()); FrameLayout.LayoutParams lpText = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER); // Note: LinearLayout.LayoutParams 's gravity was not working so I putted Framelayout as 3 paramater is gravity itself textView.setTextColor(Color.parseColor("#43A047")); textView.setLayoutParams(lpText); /*--------------end of Text view----------------------------*/ //Adding views at appropriate places frameLayout.addView(imgView); frameLayout.addView(textView); linearLayout.addView(frameLayout); } private int getPixelsToDP(int dp) { float scale = getResources().getDisplayMetrics().density; int pixels = (int) (dp * scale + 0.5f); return pixels; } 

这里工作的诀窍是我已经分配给ImageView的id“imgView.setId(v)”,然后再应用onClickListener,我再次获取视图的id ….我也在代码里面评论那容易理解,希望这个可能会非常有用…快乐编码… 🙂

http://i.stack.imgur.com/lXrpG.png

这不是一个答案,但如何使用水平滚动视图 ?

我已经做了很多search这个问题的解决scheme。 简而言之,没有好的解决办法,没有压倒一切的私人方法等等。 我发现的最好的事情是通过扩展AdapterView从头开始实现它。 这是相当悲惨的。 看到我关于水平ListViews的SO问题 。

我必须为我的一个项目做同样的事情,而且我也写了自己的作品。 我叫它HorzListView现在是我的开源Aniqroid库的一部分。

http://aniqroid.sileria.com/doc/api/ (在底部查找下载内容或使用Google代码项目查看更多下载选项: http : //code.google.com/p/aniqroid/downloads/list )

类文档在这里: http : //aniqroid.sileria.com/doc/api/com/sileria/android/view/HorzListView.html

那么你总是可以dynamic地创build你的textviews等,并设置你的onclicklisteners就像你会用一个适配器

当适配器中的数据涉及另一个线程时,Horizo​​ntialListView无法工作。 所有东西都在UI线程上运行100%。这是multithreading中的一个大问题。 我认为使用Horizo​​ntialListView并不是解决问题的最佳方法.HorzListView是一个更好的方法。您只需使用HorzListViewreplace以前的图库。您不需要修改有关适配器的代码。然后,所有内容都以您希望的方式进行。请参阅https:// stackoverflow.com/a/12339708/1525777关于HorzListView。

我在我的项目中使用了水平的listview链接 ,我得到了很好的结果。 我最初使用devsmart库,但它给了我一些问题。 所以最好的方式来使用水平的listview链接,因为它恢复了我的问题,也最近我推出了我的应用程序在谷歌PlayStore使用这个库和得到了用户的不错的回应。 所以我build议你使用我上面提到的同样的库来水平显示listview。 请享用 :)

对于我的应用程序,我使用了一个包含LinearLayout的Horizo​​ntalScrollView,其方向设置为水平。 为了在里面添加图像,我在活动中创build了ImageView,并将它们添加到我的LinearLayout中。 例如:

 <HorizontalScrollView android:id="@+id/photo_scroll" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:scrollbars="horizontal" android:visibility="gone"> <LinearLayout android:id="@+id/imageview_holder" android:layout_width="wrap_content" android:orientation="horizontal" android:layout_height="match_parent"> </LinearLayout> </HorizontalScrollView> 

这对我来说非常好。 在这个活动中,我所要做的就是下面的代码:

 LinearLayout imgViewHolder = findViewById(R.id.imageview_holder); ImageView img1 = new ImageView(getApplicationContext()); //set bitmap //set img1 layout params imgViewHolder.add(img1); ImageView img2 = new ImageView(getApplicationContext()); //set bitmap //set img2 layout params imgViewHolder.add(img2); 

正如我所说的那样对我有用,而且我希望它能帮助有人想要实现这一点。

有一个伟大的图书馆叫做TwoWayView ,实现起来非常简单,只需将项目库包含到工作空间中,并将其作为库项目添加到原始项目中,然后按照以下步骤进行:

首先,让我们在(res / values / styles.xml)中添加一个指示ListView(水平或垂直)方向的样式:

 <style name="TwoWayView"> <item name="android:orientation">horizontal</item> </style> 

然后,

在布局XML中,使用以下代码添加TwoWayView:

 <org.lucasr.twowayview.TwoWayView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/lvItems" style="@style/TwoWayView" android:layout_width="match_parent" android:layout_height="match_parent" android:drawSelectorOnTop="false" tools:context=".MainActivity" /> 

最后,像任何常规的ListView一样声明它并处理它:

 TwoWayView lvTest = (TwoWayView) findViewById(R.id.lvItems); 

ListView所有方法都像往常一样工作,但只有一个区别我注意到,即在设置select模式时, setChoiceMode方法不是接受一个int值,而是来自enum名为ChoiceMode的值,所以list_view.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 将会是lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE

您可以使用ViewFlipper来包含布局XML,并为每个布局XML添加图像,列表视图