Почему не работает атрибут `android: foreground`? - PullRequest
0 голосов
/ 14 сентября 2018

Взгляните на это маленькое приложение для Android:

MainActivity.java:

package io.github.gsaga.toucheventtest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

activity_main:

<ImageView android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="@drawable/ic_launcher_background"
    xmlns:android="http://schemas.android.com/apk/res/android" />

Изображение, на которое указывает android:foregroundне отображается, но появляется, если я изменю foreground на src или background в activity_main.xml.Кажется, этот код следует описанным здесь инструкциям:

https://developer.android.com/reference/android/view/View.html#attr_android:foreground

Почему тег android:foreground не работает в приведенном выше коде?

ПРИМЕЧАНИЕ.

minSdkVersion - это 19, я запускаю это приложение на Android 5.1 (API level 22)

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

Однажды (API <23) похоже, что <code>android:foreground будет работать только с FrameLayout, как предлагает VicJordan.Однако для API 23+ android:foreground будет работать для любого типа представления.См. этот выбор из View.java источника:

case R.styleable.View_foreground:
    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
        setForeground(a.getDrawable(attr));
}

Вот пример android:foreground, работающего над API 28 со следующим макетом:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:foreground="@drawable/ic_launcher_foreground"
        android:src="@android:drawable/ic_delete"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

enter image description here

Тем не менее, в API 22 мы видим это:

enter image description here

Нет изображения переднего плана.Таким образом, android:foreground работает только при уровне API 23+.Я согласен, что это на самом деле не задокументировано, но так оно и есть.

Обновление: API 23, похоже, имеет проблему с android:foreground, так что давайте скажем android:foregroundработает с API 24+ для общих видов.

Второе обновление: Наткнулся на пару других постов, посвященных этой же проблеме, касающихся setForeground() здесь и здесь .В принятом ответе на второй вопрос CommonsWare определяет это как «ошибку документации».

0 голосов
/ 19 сентября 2018

Краткий ответ

Это связано с ошибкой, существующей в Android начиная с уровня API 23.


Подробнее о поведении

Здесь приведен список всех атрибутов XML и соответствующих методов, связанных с настройкой объектов рисования переднего плана для представлений с уровнем API, который они вводят через FrameLayout. Однако позже они перемещены в View на уровне API 23.

╔════════════════════════════╦═════════════════════════════════════════════════╦═════════════╗
║       XML attribute        ║                     Method                      ║   Added in  ║
║                            ║                                                 ║ (API level) ║
╠════════════════════════════╬═════════════════════════════════════════════════╬═════════════╣
║ android:foreground         ║ setForeground(Drawable)                         ║ 1           ║
╠════════════════════════════╬═════════════════════════════════════════════════╬═════════════╣
║ android:foregroundGravity  ║ setForegroundGravity(int gravity)               ║ 1           ║
╠════════════════════════════╬═════════════════════════════════════════════════╬═════════════╣
║ android:foregroundTint     ║ setForegroundTintMode(PorterDuff.Mode tintMode) ║ 21          ║
╠════════════════════════════╬═════════════════════════════════════════════════╬═════════════╣
║ android:foregroundTintMode ║ setForegroundTintMode(PorterDuff.Mode tintMode) ║ 21          ║
╚════════════════════════════╩═════════════════════════════════════════════════╩═════════════╝
  • Документ Android сообщает, что setForeground(Drawable) добавлено в API 1, а setForegroundTintList (ColorStateList tint) и setForegroundTintMode (PorterDuff.Mode tintMode) добавлены в API уровня 21 до View. Это неверно. Были в FrameLayout до API 23.

  • На уровне API <23 вы получите предупреждение, даже если оно не требуется. Вы можете просто подавить это. См <a href="https://issuetracker.google.com/issues/37065042" rel="noreferrer"> это .


Теперь посмотрим, как эти свойства работают в разных версиях.

╔═══════════╦══════════════════╦══════════════════╗
║ API level ║      By code     ║     Using XML    ║
╠═══════════╬══════════════════╬══════════════════╣
║ <23       ║ FrameLayout only ║ FrameLayout only ║
╠═══════════╬══════════════════╬══════════════════╣
║ >=23      ║ FrameLayout only ║ All views        ║
╚═══════════╩══════════════════╩══════════════════╝


Причина ошибки

Когда эти свойства перешли на View на уровне API 23, они сделали некоторые странные изменения, которые можно назвать ошибкой. При загрузке свойств из XML он проверяет, является ли View FrameLayout, которого нет внутри методов, которые мы можем использовать для той же цели.

Конструктор представлений, уровень API 23:

case R.styleable.View_foreground:
    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
        setForeground(a.getDrawable(attr));
    }
    break;
0 голосов
/ 16 сентября 2018

Чтобы использовать android:foreground на Android 5.1, то есть API level 22, вы не используете android:foreground правильно.

Поскольку это имя ясно указывает на то, что вы можете установить рисование на верхнем / переднем плане любого контента, например наложения, т.е. вы можете поместить некоторое представление в FrameLayout, в котором вы можете использовать android:foreground.Внутри этого FrameLayout добавьте ImageView.

Документация :

Определяет рисование для рисования поверх содержимого .Это можно использовать как оверлей .Drawable переднего плана участвует в заполнении содержимого, если гравитация установлена ​​для заполнения.

Ниже приведен пример использования:

<FrameLayout
    android:id="@+id/share"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:foreground="@drawable/ic_launcher_background>

    // your ImageView here
    <ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</FrameLayout>

Примечание: ДляAPI level > 23 это будет работать без FrameLayout.

Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...