如何在 Android 中制作水平 ListView? [英] How can I make a horizontal ListView in Android?

查看:22
本文介绍了如何在 Android 中制作水平 ListView?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

就像 Android 中的许多事情一样,您不会认为这会是一个如此困难的问题,但是天哪,您会错吗.而且,就像 Android 中的许多东西一样,API 甚至没有提供一个合理可扩展的起点.如果我要滚动我自己的 ListView,我会被诅咒,而我想要的只是把它拿走,然后把它放在一边. ant

Like many things in Android, you wouldn't think this would be such a hard problem but ohhh, by golly, would you be wrong. And, like many things in Android, the API doesn't even provide a reasonably extensible starting point. I'll be damned if I'm going to roll my own ListView, when all I want is to take the thing and turn it on its side. ant

好的,现在我已经完成了,让我们谈谈问题本身.我需要的基本上与 Gallery 完全一样,但没有中心锁定功能.我真的不需要 ListView 的 listSelector 但它是一个很好的工具.大多数情况下,我可以使用 ScrollView 内的 LinearLayout 做我想做的事情,但我需要子视图来自 ListAdapter,我会真的很喜欢有一个视图回收器.而且我真的不想写任何布局代码.

Okay, now that I'm done fuming, let's talk about the problem itself. What I need is basically something exactly like the Gallery, but without the center-locking feature. I don't really need ListView's listSelector but it's a nice-to-have. Mostly, I could do what I want with a LinearLayout inside a ScrollView, but I need the child views to come from a ListAdapter and I would really like to have a view recycler. And I really don't want to write any layout code.

我查看了其中一些类的源代码...

I peeked into the source code for some of these classes...

画廊:如果我覆盖大多数onXyz"方法,复制它们的所有源代码,但不要调用scrollIntoSlots().但我敢肯定,如果我这样做,我会遇到一些无法访问的成员字段或其他一些不可预见的后果.

Gallery: It looks like I could use the Gallery if I override most of the 'onXyz' methods, copy all their source code, but refrain from calling scrollIntoSlots(). But I'm sure that if I do that I'll run into some member field that's inaccessible or some other unforeseen consequence.

AbsSpinner: 由于 mRecycler 字段是包私有的,我怀疑我是否能够扩展这个类.

AbsSpinner: Since the mRecycler field is package-private I doubt I'll be able to extend this class.

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

AbsListView: It looks like this class is only meant for vertical scrolling, so no help there.

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

AdapterView: I've never had to extend this class directly. If you tell me it's easy to do, and that it's easy to roll my own RecycleBin, I'll be very skeptical but I'll give it a shot.

我想我可以复制两个 AbsSpinnerGallery 来得到我想要的......希望这些类没有使用一些包私有变量我无法访问.你们都认为这是一个好习惯吗?有没有人有任何教程或第三方解决方案可以帮助我找到正确的方向?

I suppose I could possibly copy both AbsSpinner and Gallery to get what I want... hopefully those classes aren't using some package-private variable I can't access. Do y'all think that's a good practice? Does anyone have any tutorials or third-party solutions that might put me in the right direction?

更新:
到目前为止,我找到的唯一解决方案是自己完成所有工作.自从提出这个问题以来,我已经覆盖了 AdapterView 并从头开始实现了我自己的Horizo​​ntalListView".真正覆盖 Gallery 的中心锁定功能的唯一方法是覆盖私有的 scrollIntoSlots 方法,我认为这需要在运行时生成一个子类.如果您有足够的勇气这样做,这可以说是最好的解决方案,但我不想依赖可能会改变的未记录方法.

Update:
The only solution I've found so far is to do it all myself. Since asking this question, I have overridden AdapterView and implemented my own "HorizontalListView" from scratch. The only way to truly override the Gallery's center-locking feature is to override the private scrollIntoSlots method, which I believe would require generating a subclass at runtime. If you're bold enough to do that, it's arguably the best solution, but I don't want to rely on undocumented methods that could change.

下面的 Swathi EP 建议我给 Gallery 一个 OnTouchListener 并覆盖滚动功能.如果你不关心在你的列表中是否有投掷支持,或者如果视图在投掷动画结束时捕捉到中心是可以的,那么这 对你有用!然而,最终证明在不移除抛掷支撑的情况下移除中心锁定功能仍然是不可能的.我问你,什么样的清单不会丢?

Swathi EP below suggested that I give the Gallery an OnTouchListener and override the scroll functionality. If you don't care about having fling support in your list, or if it's okay for the views to snap to the center at the end of the fling animation, then this will work for you! However, in the end it still proves impossible to remove the center-locking feature without removing fling support. And I ask you, what kind of list doesn't fling?

所以,唉,这对我不起作用.:-( 但如果您对这种方法感兴趣,请继续阅读...

So, alas, this did not work for me. :-( But if you're interested in this approach, read on...

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

I also had to make some additions to Swathi's code to get what I wanted. In GestureListener.onTouch, in addition to delegating to the gesture detector, I also had to return true for ACTION_UP and ACTION_CANCEL events. That successfully disabled the center-locking feature, but it also disabled flinging. I was able to re-enable fling by having my own GestureListener delegate to the Gallery's onFling method. If you want to try it out, go into your ApiDemos sample code and replace the Gallery1.java class with the following code:

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.你可以在这里找到它:http://dev-smart.com/horizo​​ntal-listview/如果这有帮助,请告诉我.

After reading this post, I have implemented my own horizontal ListView. You can find it here: http://dev-smart.com/horizontal-listview/ Let me know if this helps.

这篇关于如何在 Android 中制作水平 ListView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆