【问题标题】:Is vertical scrolling in layouts suppressed when used in a GridViewPager in Android Wear?在 Android Wear 的 GridViewPager 中使用时,布局中的垂直滚动是否受到抑制?
【发布时间】:2015-03-11 23:40:54
【问题描述】:

在我的 Android Wear 应用程序中,我使用 GridViewPager 并排显示两个布局,您可以在它们之间水平滑动。一页有一个 ScrollView 和子元素。另一个页面有一个用于 WearableListView 的 BoxInsetLayout 和 FrameLayout。如果我在没有 GridViewPager 的情况下单独显示每个页面,我可以很好地滚动 ScrollView 中的文本,并且可以很好地滚动 WearableListView 中的项目列表。但是,当我在 GridViewPager 中将两个页面放在一起时,我不能向上或向下滚动其中的元素,至少在我的 Moto360 上不能。 ScrollView 会在圆形 Android 模拟器中垂直滚动,但 WearableListView 不会。

要么我做错了什么,要么它不应该那样工作。

我的主要 java 类有:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.context = this;
    setContentView(R.layout.activity_wear);

    GridViewPager pager = (GridViewPager) findViewById(R.id.activity_wear_pager);
    pager.setAdapter(new gridViewPagerAdapter());

    DotsPageIndicator dotsPageIndicator = (DotsPageIndicator) findViewById(R.id.activity_wear_page_indicator);
    dotsPageIndicator.setPager(pager);
}
private class gridViewPagerAdapter extends GridPagerAdapter {
    @Override
    public int getColumnCount(int arg0) { return 2; }

    @Override
    public int getRowCount() { return 1; }

    @Override
    protected Object instantiateItem(ViewGroup container, int row, int col) {
        View view = null;

        if (col == 0) {
            view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.read_page_round, container, false);
            mTextView = (TextView)   view.findViewById(R.id.text);
        }
        else {
            view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.find_page_round, container, false);
            listView =  (WearableListView) view.findViewById(R.id.wearable_list);
            listView.setAdapter(new Adapter(getApplicationContext(), elements));
            listView.setClickListener(WearApplication.this);
        }

        container.addView(view);
        return view;
    }

    @Override
    protected void destroyItem(ViewGroup container, int row, int col, Object view) {
        container.removeView((View)view);
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view==object;
    }
}

activity_wear.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.wearable.view.GridViewPager
        android:id="@+id/activity_wear_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:keepScreenOn="true"/>

    <android.support.wearable.view.DotsPageIndicator
        android:id="@+id/activity_wear_page_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|bottom">
    </android.support.wearable.view.DotsPageIndicator>
</FrameLayout>

read_page_round.xml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WearApplication"
tools:deviceIds="wear_round">
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="5dp"
        android:paddingRight="15dp"
        android:paddingBottom="60dp"
        android:paddingLeft="15dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        style="@style/wear_main_text"/>

    (Other TextView items)

</LinearLayout>
</ScrollView>

find_page_round.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.BoxInsetLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/white"
android:layout_height="match_parent"
android:layout_width="match_parent">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:gravity="center_vertical|center_horizontal"
        android:text="Select List"
        style="@style/wear_main_app"/>
    <FrameLayout
        android:id="@+id/frame_layout"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        app:layout_box="left|bottom|right">
        <android.support.wearable.view.WearableListView
            android:id="@+id/wearable_list"
            android:layout_height="match_parent"
            android:layout_width="match_parent">
        </android.support.wearable.view.WearableListView>
    </FrameLayout>
</LinearLayout>
</android.support.wearable.view.BoxInsetLayout>

【问题讨论】:

    标签: android wear-os


    【解决方案1】:

    我想我刚刚遇到了同样的问题并设法解决了它(但它并不那么漂亮)。

    所以这是我的问题: 我有一个包含 DotsPageIndicator 和 GridViewPager 的视图。起初,所有东西都捆绑在一个 RelativeLayout 中。但在我的一个 GridViewPager 页面中,我想使用 BoxInsetLayout。但是,根据 StackOverflow 的几个答案,我发现 BoxInsetLayout 必须是您活动的根元素。因此,我将 DotsPageIndicator 和 GridViewPager 捆绑在 BoxInsetLayout 中,但如果将插入 (app:layout_box="all") 应用到我的 GridViewPager 孩子之一上,它就不起作用了...

    为什么它不起作用: 我有点愚蠢,只允许 BoxInsetLayout 作为 Activity 的根视图......但是这是规则,所以我们必须使用它。但是,您似乎不能在任何级别的视图上应用插入规则,只能在 BoxInsetLayout 下一层的视图上应用。所以就我而言,这意味着我只能将插图应用于 DotsPageIndicator 和 GridViewPager。这不是我想要的。

    如何解决此限制: 因此,这是我在布局文件中解决此限制的方法:

    <android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                                  xmlns:app="http://schemas.android.com/apk/res-auto"
                                                  android:layout_width="match_parent"
                                                  android:layout_height="match_parent"
                                                  android:background="@drawable/balance_detail_background_full">
    
        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_box="all"
            android:background="@android:color/transparent"
            android:id="@+id/dummy_view"/>
    
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent">
    
            <android.support.wearable.view.DotsPageIndicator
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/view_pager_indicator"
                android:layout_alignParentBottom="true"
                android:layout_centerHorizontal="true"
                android:layout_marginBottom="4dp"/>
    
            <be.belfius.directmobile.android.wearable.widget.FixedGridViewPager
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/view_pager"/>
        </RelativeLayout>
    </android.support.wearable.view.BoxInsetLayout>
    

    所以对于第一部分,您可以看到我添加了一个具有透明背景的“虚拟”视图,它设置 BoxInsetLayout 以在完美圆形手表上为我提供漂亮的方形视图。但是,在 ViewPager 子视图中,这不会影响任何内容。 但我接下来要做的是通过我的 ViewPagerAdapter(在我的例子中是 SingleRowGridPagerAdapter)将这个视图从我的 Activity 传递给我的子视图。

    所以在代码中,我的 onCreate(..) 方法看起来像这样:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.my_layout);
    
        View dummyBoxInsetView = findViewById(R.id.dummy_view);
        mViewPager = findViewById(R.id.view_pager);
        mViewPagerIndicator = findViewById(R.id.view_pager_indicator);
        mAdapter = new MyViewPagerAdapter(YOUR_PARAMS, dummyBoxInsetView);
        mViewPager.setAdapter(mAdapter);
        mViewPagerIndicator.setPager(mViewPager);
    }
    

    在您的自定义视图寻呼机中,您将初始化所有子视图(页面),对于您想要的页面,您可以执行以下操作:

    public void setReferenceBoxInsetLayoutView(View boxInsetLayoutView) {
        int inboxOffsetLeft = boxInsetLayoutView.getPaddingLeft();
        int inboxOffsetRight = boxInsetLayoutView.getPaddingRight();
        int inboxOffsetTop = boxInsetLayoutView.getPaddingTop();
        int inboxOffsetBottom = boxInsetLayoutView.getPaddingBottom();
    
        MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mViewThatNeedsOffsets.getLayoutParams();
        marginLayoutParams.leftMargin = inboxOffsetLeft;
        marginLayoutParams.rightMargin = inboxOffsetRight;
        marginLayoutParams.topMargin = inboxOffsetTop;
        marginLayoutParams.bottomMargin = inboxOffsetBottom;
        mViewThatNeedsOffsets.setLayoutParams(marginLayoutParams);
    }
    

    如您所见,您的视图所需的偏移量由 BoxInsetLayout 在参考视图上设置为边距。如果您只需要左右,或上下,甚至一个随意...现在都在您手中。

    我知道这是一个肮脏的解决方案,但它是迄今为止最好的解决方案,在搜索了好几个小时之后,以我们想要的方式完成圆形手表的工作。

    为了提高性能,您可以在布局文件中将虚拟视图(又名 dummyBoxInsetView)的可见性设置为“不可见”。这样它仍然会被测量但不会被绘制。没有测试 visiblity="gone" 但我想这不会起作用,因为视图不再被测量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      • 2015-05-12
      • 2011-11-19
      • 1970-01-01
      • 2013-05-13
      • 1970-01-01
      • 2019-12-11
      相关资源
      最近更新 更多