Как обнаружить круглый экран на Android Wear - onApplyWindowInsets не вызывается на устройстве
Я реализовал обратный вызов onApplyWindowInsets в проекте Android Wear. В методе он вызывает метод isRound(), чтобы определить, выполняется ли код в круглых или прямоугольных смарт-часах Wear. Этот обратный вызов вызывается из эмулятора круглого износа. (Хотя isRound() возвращает false, что неверно.) Но проблема в том, что обратный вызов onApplyWindowInsets никогда не вызывается из моего Samsung Gear Live. Таким образом, если один раздувает представление из onApplyWindowInsets, представления не становятся раздутыми. Кто-нибудь получил на ApplyWindowInsets для запуска на реальном устройстве? Кажется, это не гарантировано. Если так, то как можно раздувать разные виды в зависимости от типа экрана?
4 ответа
В вашем макете вы можете установить конкретные "под" макеты для круглых / прямоугольных экранов:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.wearable.view.WatchViewStub
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/stub"
app:rectLayout="@layout/rect_layout"
app:roundLayout="@layout/round_layout"/>
</FrameLayout>
Если вы используете разные идентификаторы для rect_layout и round_layout, вы можете проверить это на onCreate, например так:
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.main_activity);
WatchViewStub stub = (WatchViewStub) findViewById(R.id.stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
mRectBackground = (RelativeLayout) findViewById(R.id.rect_layout);
mRoundBackground = (RelativeLayout) findViewById(R.id.round_layout);
}
});
}
Либо mRectBackground, либо mRoundBackground не будут равны NULL, а не оба. Документы здесь: https://developer.android.com/training/wearables/apps/layouts.html
Другие люди пытаются использовать стратегию использования setOnApplyWindowInsetsListener, как показано здесь: https://github.com/xamarin/monodroid-samples/blob/master/wear/GridViewPager/GridViewPager/MainActivity.cs. Это не сработало для меня.
onApplyWindowInsets
на самом деле требует, чтобы разработчик позвонил WatchViewStub
"s onApplyWindowInsets
метод внутри слушателя. Например:
WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@Override
public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
//////////////////////////////////////////////////
// IMPORTANT - the following line is required
stub.onApplyWindowInsets(windowInsets);
// Set the instance variable to say whether this is round...
mIsRound = windowInsets.isRound();
return windowInsets;
}
});
Хотя это может показаться неочевидным с первого взгляда, это позволяет разработчику переопределить настройки по умолчанию onApplyWindowInsets
реализация, если они выбирают.
Документация для View.OnApplyWindowInsetsListener
заявляет, что: "Слушатель может при необходимости вызвать метод onApplyWindowInsets параметра View, чтобы применить нормальное поведение View как часть его собственного".
Спасибо, Eider! Ваша умная техника, кажется, исправила эту проблему. (Я говорю "кажется", поскольку я не буду знать наверняка, пока код не будет протестирован на реальном круглом устройстве, которое устанавливает для mRoundBackground ненулевое значение.)
Теперь, когда есть три формы Android Wear (прямоугольник / квадрат, круг с подбородком и полный круг), я добавил два глобальных значения, чтобы найти форму экрана, а затем изменил обратный вызов следующим образом:
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
//mRectBackground = (RelativeLayout) findViewById(R.id.LinearLayout1);
mRoundBackground = (RelativeLayout) findViewById(R.id.LinearLayout2);
if (mRoundBackground != null) round = true;
else round = false;
WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = window.getDefaultDisplay();
//Added android.graphics.Point to imports for this next section
Point point = new Point (0,0);
display.getSize(point);
scrnHeight = point.y;
scrnWidth = point.x;
if (round && scrnWidth == scrnHeight) chin = false;
else chin = true;
//round = true; //For testing on the emulator!!!!!!
}
});
Кто-нибудь знает лучший способ обнаружить подбородок на Moto360?
ОБНОВЛЕНИЕ: Просто запустил этот код на Moto 360, и этот метод НЕ обнаружил круглый экран. Так что сейчас я просто определяю, равна ли высота ширине. Но это плохая техника для будущего, когда появятся новые устройства Android Wear. Таким образом, вопрос все еще остается, как определить круглый экран на реальных устройствах Android Wear, которые там есть?
Неофициальный способ (без использования WatchViewStub) - но для меня это было намного проще. https://github.com/tajchert/ShapeWear
Просто скопируйте класс ShapeWear.java и подпишитесь на событие определения формы экрана setOnShapeChangeListener()
или вызов метода ShapeWear.isRound()
(может выдать ошибку, если форма еще не определена) или ShapeWear. getShape()
- что может привести к ShapeWear.SHAPE_UNSURE
в той же ситуации.