【问题标题】:Can you use a WatchViewStub in a GridViewPager for Android Wear?您可以在 Android Wear 的 GridViewPager 中使用 WatchViewStub 吗?
【发布时间】:2015-05-12 13:53:40
【问题描述】:

我有一个独立工作的 WatchViewStub - 它在适当的方形或圆形 android wear 模拟器上显示正确的布局。但是当我尝试在 GridViewPager 中使用 WatchViewStub 时,即使在圆形模拟器上,它也总是显示方形(或矩形)布局。两者一起使用成功吗?

以下是一些代码片段:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    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);
}

这里是 gridViewPagerAdapter:

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_stub, container, false);
            WatchViewStub stub = (WatchViewStub) view.findViewById(R.id.read_page_stub);
            stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
                @Override
                public void onLayoutInflated(WatchViewStub stub) {
                }
            });
        }
        else {
            view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.find_page_stub, container, false);
            WatchViewStub stub = (WatchViewStub) view.findViewById(R.id.find_page_stub);
            stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
                @Override
                public void onLayoutInflated(WatchViewStub stub) {
                }
            });
        }

        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_stub.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.WatchViewStub
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/read_page_stub"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:rectLayout="@layout/read_page_rect"
    app:roundLayout="@layout/read_page_round"
    tools:context=".WearApplication"
    tools:deviceIds="wear">
</android.support.wearable.view.WatchViewStub>

然后我的视图有两个布局。他们开始于:

read_page_rect.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_square">

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">

我为 find_page_stub、find_page_rect 和 find_page_round 设置了相同类型的布局设置。

【问题讨论】:

  • 另一种方法是使用 FragmentGridPagerAdapter(扩展 GridPagerAdapter)并以 SomeFragment.newInstance(listOfObjects.get(row)); 的方式在 getFragment(...) 中填充片段;然后在 SomeFragment 的 onCreateView 中执行 WatchViewStub 的工作。这对我来说效果很好,我不需要处理 WindowInsets。

标签: android wear-os


【解决方案1】:

正如@gruszczy 提到的,GridViewPager 默认使用 WindowsInsets 回调。解决此问题的方法是手动将其设置为不通过代码执行:

mGridViewPager.setConsumeWindowInsets(false);

此方法设置一个内部布尔属性,用于 insets 的调度程序方法。可以在这里看到:

 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
    insets = this.onApplyWindowInsets(insets);
    if(this.mOnApplyWindowInsetsListener != null) {
        this.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
    }

    return this.mConsumeInsets?insets.consumeSystemWindowInsets():insets;
}

最后一点,这是在 Support Wearable 库的 1.3.0 版上。我不确定这是否包含在以前的版本中...

【讨论】:

    【解决方案2】:

    如果WatchViewStub 没有显示圆形布局,则意味着它没有正确接收WindowInsets 对象。 GridViewPager 一定是在路上的某个地方吃掉它。

    您可以尝试修复它。这样做的方法是(首先是一些理论):

    1) 从阅读 View.dispatchApplyWindowInsetsView.onApplyWindowInsets 开始

    2) 这两个方法绑定在View 中的方式是这样的:dispatchApplyWindowInsets 被调用并检查是否有任何监听器;如果是,它只将WindowInsets 传递给listener;如果没有,它会将WindowInsets 传递给onApplyWindowInsets

    3) 在ViewGroup (而GridViewPagerViewGroup)中,它遍历子元素并检查插入是否被消耗;如果是,它会停止交付它们;

    4) 在任何时候任何View/ViewGroup 都可以决定停止发送WindowInsets;当它这样做时,任何依赖它的孩子都不会在回合中正常表现;

    现在进行一些练习:

    5) 您可以创建层次结构中任何视图的子类;使用GridViewPager 执行此操作并开始尝试覆盖dispatchApplyWindowInsetsonApplyWindowInsets。我的猜测是第一个应该足够了。

    6) 在 dispatchApplyWindowInsets 的覆盖中遍历子代并调用 dispatchApplyWindowInsets 给每个子代;这样WatchViewStub 应该会收到与之前的isRound()-&gt;true 方法相同的WindowInsets

    7) 最后别忘了拨打super.dispatchApplyWindowInsets(windowInsets);你想让GridViewPager 用插图做它需要做的事情。

    唷,很长,但应该对您有所帮助,并让您了解为什么事情会以这种方式发生。我认为我们有一个 bug 可以修复这个 GridViewPager 问题,所以也许在下一个版本之后你就不必处理这个了。

    【讨论】:

    • 感谢您的信息,这很有帮助,尽管我正在努力实现您的子类想法 - 我遇到了一个不知道如何解决的类转换异常。无论如何,这听起来像是 Android Wear 中的一个错误,所以此时我最好的做法可能是放弃 WatchViewStub 方法,让我的布局与 rect/round 相同,或者找到一种动态确定形状的方法。
    • 您看到的异常是什么?你能更新你的问题吗?
    猜你喜欢
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    相关资源
    最近更新 更多