如何在Android中创建可滚动的旋转页面?

pau*_*ode 35 android carousel android-layout

我正在尝试为我的Android应用程序构建一个UI,其中包含一个可垂直滚动的可水平滚动轮播页面(类似于Netflix应用程序的功能).这种行为是如何完成的?

一个基本的实现就足以让我开始.UI还有一些其他要求,我将在此处作为参考,因为它可能会影响我可以使用的类或库.

1)旋转木马之间的垂直滚动应该是平滑的,但是当用户释放时,UI应该"捕捉"最近的旋转木马(因此用户总是在旋转木马行上,而不是在两个旋转木马之间).

2)旋转木马上的水平滚动应该是平滑的,但是当用户释放时,UI应该"捕捉"旋转木马中最近的项目.

3)应该可以在转盘中的项目上叠加附加信息

4)UI应适应任何屏幕尺寸.

5)应使用箭头键导航(适用于无触摸屏的设备)

6)应该适用于各种Android版本(可能通过支持库)

7)应该可以在根据GPL许可的开源应用程序中使用

可接受的答案不必满足所有这些要求.至少,一个好的答案应该涉及导航多个轮播(而不是只有一个轮播).

这是一个基本上我想象的模型(我很灵活,不必看起来像这样......只是为了澄清我在谈论的内容 - 每一行都包含很多可能的项目向左和向右滚动,整个页面可以上下滚动)

在此输入图像描述

mml*_*loo 47

大意

为了有一个灵活的设计,并具有无限的项目,你可以创建一个RecyclerView为具有一个根视图LinearLayoutManager.VERTICALLayoutManager.对于每一行你可以放另一行,RecyclerView但现在用a LinearLayoutManager.HORIZONTAL作为LayoutManager.

结果

在此输入图像描述

资源

要求

1)旋转木马之间的垂直滚动应该是平滑的,但是当用户释放时,UI应该"捕捉"最近的旋转木马(因此用户总是在旋转木马行上,而不是在两个旋转木马之间).

2)旋转木马上的水平滚动应该是平滑的,但是当用户释放时,UI应该"捕捉"旋转木马中最近的项目.

为了实现我使用的那些OnScrollListener以及当状态为SCROLL_STATE_IDLE时,我检查顶视图和底视图以查看哪些具有更多可见区域然后滚动到该位置.对于每一行,我为每个行适配器的左视图和右视图执行此操作.这样,旋转木马或行的一侧总是适合.例如,如果安装顶部,则底部不是,反之亦然.我想如果你再玩一点,你可以实现这一目标,但你必须知道窗口的尺寸,并在运行时改变轮播的尺寸.

3)应该可以在转盘中的项目上叠加附加信息

如果您使用RelativeLayoutFrameLayout作为每个项目的根视图,您可以将信息放在彼此之上.正如您所看到的那样,数字位于图像的顶部.

4)UI应适应任何屏幕尺寸.

如果您知道如何支持多种屏幕尺寸,则可以轻松完成,如果您不知道阅读文档. 支持多个屏幕

5)应使用箭头键导航(适用于无触摸屏的设备)

使用以下功能

mRecyclerView.scrollToPosition(position);
Run Code Online (Sandbox Code Playgroud)

6)应该适用于各种Android版本(可能通过支持库)

导入android.support.v7 .widget.RecyclerView;

7)应该可以在根据GPL许可的开源应用程序中使用

快乐的编码!!

  • 这是一个非常好的,非常彻底的答案.谢谢! (2认同)

Mos*_*zar 6

您可以使用ListView控件与自定义OnTouchListener(用于捕捉项目)的垂直滚动和TwoWayGridView再次与自定义OnTouchListener(用于捕捉项目)

在此输入图像描述

main.xml中

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/containerList"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:background="#E8E8E8"
    android:divider="@android:color/transparent"
    android:dividerHeight="16dp" />
Run Code Online (Sandbox Code Playgroud)

list_item_hgrid.xml

<com.jess.ui.TwoWayGridView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/grid"
    android:layout_width="match_parent"
    android:layout_height="160dp"
    android:layout_marginBottom="16dp"
    app:cacheColorHint="#E8E8E8"
    app:columnWidth="128dp"
    app:gravity="center"
    app:horizontalSpacing="16dp"
    app:numColumns="auto_fit"
    app:numRows="1"
    app:rowHeight="128dp"
    app:scrollDirectionLandscape="horizontal"
    app:scrollDirectionPortrait="horizontal"
    app:stretchMode="spacingWidthUniform"
    app:verticalSpacing="16dp" />
Run Code Online (Sandbox Code Playgroud)

活动代码将如下所示

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test);

    ListView containerList = (ListView) findViewById(R.id.containerList);
    containerList.setAdapter(new DummyGridsAdapter(this));
    containerList.setOnTouchListener(mContainerListOnTouchListener);
}

private View.OnTouchListener mContainerListOnTouchListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                View itemView = ((ListView) view).getChildAt(0);
                int top = itemView.getTop();
                if (Math.abs(top) >= itemView.getHeight() / 2) {
                    top = itemView.getHeight() - Math.abs(top);
                }

                ((ListView) view).smoothScrollBy(top, 400);
        }

        return false;
    }
};
Run Code Online (Sandbox Code Playgroud)

这是测试适配器

private static class DummyGridsAdapter extends BaseAdapter {

    private Context mContext;

    private TwoWayGridView[] mChildGrid;

    public DummyGridsAdapter(Context context) {
        mContext = context;

        mChildGrid = new TwoWayGridView[getCount()];
        for (int i = 0; i < mChildGrid.length; i++) {
            mChildGrid[i] = (TwoWayGridView) LayoutInflater.from(context).
                    inflate(R.layout.list_item_hgrid, null);
            mChildGrid[i].setAdapter(new DummyImageAdapter(context));
            mChildGrid[i].setOnTouchListener(mChildGridOnTouchListener);
        }
    }

    @Override
    public int getCount() {
        return 8;
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return mChildGrid[position];
    }

    private View.OnTouchListener mChildGridOnTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_UP:
                    View itemView = ((TwoWayGridView) view).getChildAt(0);
                    int left = itemView.getLeft();
                    if (Math.abs(left) >= itemView.getWidth() / 2) {
                        left = itemView.getWidth() - Math.abs(left);
                    }

                    ((TwoWayGridView) view).smoothScrollBy(left, 400);
            }

            return false;
        }
    };

}

private static class DummyImageAdapter extends BaseAdapter {

    private Context mContext;

    private final int mDummyViewWidthHeight;

    public DummyImageAdapter(Context context) {
        mContext = context;

        mDummyViewWidthHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 128,
                context.getResources().getDisplayMetrics());
    }

    @Override
    public int getCount() {
        return 16;
    }

    @Override
    public Object getItem(int position) {
        int component = (getCount() - position - 1) * 255 / getCount();
        return Color.argb(255, 255, component, component);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView = new ImageView(mContext);
        imageView.setBackgroundColor((Integer) getItem(position));
        imageView.setLayoutParams(new TwoWayGridView.LayoutParams(mDummyViewWidthHeight, mDummyViewWidthHeight));
        return imageView;
    }

}
Run Code Online (Sandbox Code Playgroud)