如何在Android中制作水平的ListView?

可能重复:
Android中的水平ListView?

就像Android中的许多事情一样,你不会认为这会是一个很难的问题,但是哦,高尔德,你会错的。 而且,就像Android中的许多事情一样,API甚至没有提供合理的可扩展的起点。 如果我要推出我自己的ListView,那么我只会把所有的东西拿起来,把它放在一边。 \咆哮

好吧,现在我已经完成了冒烟,让我们来谈谈问题本身。 我所需要的基本上与Gallery相似,但没有中央lockingfunction。 我真的不需要ListView的listSelector,但它是一个很好的。 大多数情况下,我可以用ScrollViewLinearLayout来做我想做的事情,但我需要来自ListAdapter的子视图,而且我真的希望有一个视图回收器。 我真的不想写任何布局代码。

我偷看了一些这些类的源代码…

图库:如果我重写大部分'onXyz'方法,就可以使用图库,复制所有的源代码,但不要调用scrollIntoSlots() 。 但是我确信,如果我这样做,我会遇到一些无法访问或其他不可预见的后果的成员字段。

AbsSpinner:由于mRecycler字段是包私人的,我怀疑我可以扩展这个类。

AbsListView:它看起来像这个类只适用于垂直滚动,所以没有帮助。

AdapterView:我从来没有直接扩展这个类。 如果你告诉我这很容易做,而且很容易推出我自己的RecycleBin ,我会非常怀疑,但我会给它一个。

我想我可以复制AbsSpinnerGallery来得到我想要的…希望这些类不使用我无法访问的一些package-privatevariables。 你们都认为这是一个很好的做法吗? 有没有人有任何教程或第三方解决scheme,可能使我在正确的方向吗?

更新:
我迄今为止唯一find的解决scheme就是自己做。 由于提出这个问题,我重写了AdapterView并从头开始实现我自己的“Horizo​​ntalListView”。 要真正覆盖图库的中心lockingfunction的唯一方法是重写私有scrollIntoSlots方法,我相信这将需要在运行时生成一个子类。 如果你敢于这样做,这可以说是最好的解决scheme,但我不想依赖可能改变的无证方法。

下面的Swathi EPbuild议我给Gallery一个OnTouchListener并重写滚动function。 如果你不关心在列表中是否有支持,或者如果可以在videoanimation结束时将视图捕捉到中心,那么这对你来说是有效的! 然而,最终仍然不能移除中央lockingfunction而不去除支撑。 我问你,什么样的名单不投掷?

所以,唉,这不适合我。 :-(但如果你对这种方法感兴趣,请继续阅读…

为了得到我想要的,我还必须对Swathi的代码做一些补充。 在GestureListener.onTouch ,除了委托给手势检测器之外,我还必须为ACTION_UPACTION_CANCEL事件返回true。 这成功地禁用了中央lockingfunction,但它也禁用了投掷。 我能够通过将自己的GestureListener委托给Gallery的onFling方法来重新启用onFling 。 如果您想尝试一下,请进入ApiDemos示例代码,并用以下代码replaceGallery1.java类:

 import com.example.android.apis.R; import android.app.Activity; import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; import android.view.ContextMenu; import android.view.GestureDetector; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ContextMenu.ContextMenuInfo; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.View.OnTouchListener; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageView; import android.widget.Toast; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; public class Gallery1 extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gallery_1); // Reference the Gallery view final Gallery g = (Gallery) findViewById(R.id.gallery); // Set the adapter to our custom adapter (below) g.setAdapter(new ImageAdapter(this)); // Set a item click listener, and just Toast the clicked position g.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { Toast.makeText(Gallery1.this, "" + position, Toast.LENGTH_SHORT).show(); } }); // Gesture detection final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector(g)); OnTouchListener gestureListener = new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { boolean retVal = gestureDetector.onTouchEvent(event); int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { retVal = true; onUp(); } return retVal; } public void onUp() { // Here I am merely copying the Gallery's onUp() method. for (int i = g.getChildCount() - 1; i >= 0; i--) { g.getChildAt(i).setPressed(false); } g.setPressed(false); } }; g.setOnTouchListener(gestureListener); // We also want to show context menu for longpressed items in the gallery registerForContextMenu(g); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.add(R.string.gallery_2_text); } @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); Toast.makeText(this, "Longpress: " + info.position, Toast.LENGTH_SHORT).show(); return true; } public class ImageAdapter extends BaseAdapter { int mGalleryItemBackground; public ImageAdapter(Context c) { mContext = c; // See res/values/attrs.xml for the <declare-styleable> that defines // Gallery1. TypedArray a = obtainStyledAttributes(R.styleable.Gallery1); mGalleryItemBackground = a.getResourceId( R.styleable.Gallery1_android_galleryItemBackground, 0); a.recycle(); } public int getCount() { return mImageIds.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ImageView i = new ImageView(mContext); i.setImageResource(mImageIds[position]); i.setScaleType(ImageView.ScaleType.FIT_XY); i.setLayoutParams(new Gallery.LayoutParams(136, 88)); // The preferred Gallery item background i.setBackgroundResource(mGalleryItemBackground); return i; } private Context mContext; private Integer[] mImageIds = { R.drawable.gallery_photo_1, R.drawable.gallery_photo_2, R.drawable.gallery_photo_3, R.drawable.gallery_photo_4, R.drawable.gallery_photo_5, R.drawable.gallery_photo_6, R.drawable.gallery_photo_7, R.drawable.gallery_photo_8 }; } public class MyGestureDetector extends SimpleOnGestureListener { private Gallery gallery; public MyGestureDetector(Gallery gallery) { this.gallery = gallery; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return gallery.onFling(e1, e2, velocityX, velocityY); } } } 

阅读这篇文章后,我已经实现了我自己的横向ListView 。 你可以在这里find它: http : //dev-smart.com/horizo​​ntal-listview/让我知道这是否有帮助。

你有没有看过使用Horizo​​ntalScrollView来包装你的列表项目? 这将允许您的每个列表项目是可水平滚动的(您放入的内容取决于您,并且可以使它们成为类似于ListView的dynamic项目)。 如果你只是在一行项目之后,这将工作得很好。

你知道,使用现有的ListView和一些明智的覆盖dispatchDraw() (将canvas旋转90度), onTouch() (交换onTouch()坐标系的X和Y)和onMeasure()或任何愚弄它认为这是Y的X,而不是X的Y …

我不知道这是否会真正起作用,但find答案很有趣。 🙂

这可能是一个非常晚的答复,但它正在为我们工作。 我们正在使用Android提供的相同画廊,只是我们已经调整了左边距,使画面左端的画面成为画廊的中心。 这真的对我们很好。

我使用Pauls (请参阅他的答案 )Horizo​​ntalListview的实现和它的作品,非常感谢你分享!

我稍微改变了他的Horizo​​ntalListView类(顺便说一句,保罗有一个错字在你的类名,你的类名是“Horizo​​ntialListView”而不是“Horizo​​ntalListView”,“我”是太多)来更新子视图时select。

更新:我的代码,我张贴在这里是错误的,我想,当我遇到麻烦的select(我认为这与查看回收),我不得不回到绘图板…

更新2:好问题解决了,我只是评论“removeNonVisibleItems(DX);” 在“onLayout(..)”,我想这会伤害性能,但由于我只使用非常小的列表,这对我来说不是问题。

我基本上在这里使用这个教程在developerlife和刚刚用Pauls Horizo​​ntalListViewreplaceListView,并做了更改,以允许“永久”select(点击一个孩子改变它的外观,当它再次点击它改变了它)。

我是一个初学者,所以在代码中可能很多丑陋的东西,让我知道,如果你需要更多的细节。

画廊是最好的解决scheme,我试过了。 我正在一个邮件应用程序,其中显示为列表视图的收件箱中的邮件,我想要一个水平的看法,我只是将listview转换为画廊,一切工作正常,因为我需要没有任何错误。 对于滚动效果,我启用了画廊的手势监听器。 我希望这个答案可以帮助你。

你看过ViewFlipper组件吗? 也许它可以帮助你。

http://developer.android.com/reference/android/widget/ViewFlipper.html

有了这个组件,你可以附加两个或更多的查看孩子。 如果你添加一些翻译animation和捕获手势检测,你可以有一个很好的水平滚动。

我的应用程序在portraint模式下使用ListView,只是在横向模式下切换到Gallery。 他们都使用一个BaseAdapter。 这看起来像下面所示。

  setContentView(R.layout.somelayout); orientation = getResources().getConfiguration().orientation; if ( orientation == Configuration.ORIENTATION_LANDSCAPE ) { Gallery gallery = (Gallery)findViewById( R.id.somegallery ); gallery.setAdapter( someAdapter ); gallery.setOnItemClickListener( new OnItemClickListener() { @Override public void onItemClick( AdapterView<?> parent, View view, int position, long id ) { onClick( position ); } }); } else { setListAdapter( someAdapter ); getListView().setOnScrollListener(this); } 

为了处理滚动事件,我从Gallery中inheritance了我自己的小部件并覆盖了onFling()。 这是layout.xml:

  <view class="package$somegallery" android:id="@+id/somegallery" android:layout_height="fill_parent" android:layout_width="fill_parent"> </view> 

和代码:

  public static class somegallery extends Gallery { private Context mCtx; public somegallery(Context context, AttributeSet attrs) { super(context, attrs); mCtx = context; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { ( (CurrentActivity)mCtx ).onScroll(); return super.onFling(e1, e2, velocityX, velocityY); } }