问题
I have a WatchViewStub that works fine on its own - it displays the correct layout on the appropriate square or round android wear emulator. But when I try and use the WatchViewStub in a GridViewPager it always displays the square (or rectangle) layout even on the round emulator. Is it possible to use the two together successfully?
Here are some code fragments:
@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);
}
Here's the 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;
}
}
Here is 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>
Here is 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>
Then I have two layouts with my views. They start with:
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">
I have the same type of layout setup for find_page_stub, find_page_rect, and find_page_round.
回答1:
If WatchViewStub
doesn't show the round layout it means it doesn't receive the WindowInsets
object properly. GridViewPager
must be consuming it somewhere on the way.
You can try and fix it. The way to do this is (first some theory):
1) start by reading about View.dispatchApplyWindowInsets and View.onApplyWindowInsets
2) the way these two methods are tied in a View
is this: dispatchApplyWindowInsets
is called and checks if there is any listener; if yes, it delivers the WindowInsets
to the listener only; if no, it delivers the WindowInsets
to onApplyWindowInsets
.
3) in a ViewGroup
(and GridViewPager
is a ViewGroup
) it iterates over the children and checks if the insets were consumed; if yes, it stops delivering them;
4) at any point any View
/ViewGroup
can decide to stop delivering the WindowInsets
; when it does, any children depending on it won't behave properly on round;
now some practice:
5) you can create a subclass of any view you have in your hierarchy; do this with GridViewPager
and start experimenting with overriding dispatchApplyWindowInsets
and onApplyWindowInsets
. My guess is the first one should be enough.
6) in the override of dispatchApplyWindowInsets
iterate over children and call dispatchApplyWindowInsets
to every of them; this way WatchViewStub
should receive unaltered WindowInsets
with the previous isRound()->true
method
7) finally, don't forget to call super.dispatchApplyWindowInsets(windowInsets)
; you want to let GridViewPager
do what it needs with the insets.
Phew, pretty long, but should help you and also give you some understanding why things are happening the way are happening. I think we have a bug standing to fix this GridViewPager
issue, so maybe after the next release you won't have to deal with this.
回答2:
As @gruszczy mentions, the GridViewPager consumes the WindowsInsets callbacks by default. The way to fix this is to manually set it to not do it by code:
mGridViewPager.setConsumeWindowInsets(false);
This method set an internal boolean attribute that is used on the dispatcher method of the insets. As can be seen here:
public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
insets = this.onApplyWindowInsets(insets);
if(this.mOnApplyWindowInsetsListener != null) {
this.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
}
return this.mConsumeInsets?insets.consumeSystemWindowInsets():insets;
}
As a final note, this is on version 1.3.0 of the Support Wearable library. I'm not sure if this is included on previous versions...
来源:https://stackoverflow.com/questions/28975375/can-you-use-a-watchviewstub-in-a-gridviewpager-for-android-wear