Как изменить исходный контент как программный?

Я знаю, как изменить homeAsUpIndicator в файле xml стилей. Вопрос в том, как изменить его программно.

Причина, по которой я хочу это сделать, потому что в некоторых представлениях я поддерживаю боковую навигацию (скользящее меню) - нажатие кнопки заголовка вверх/назад показывает боковое меню.

В других представлениях я поддерживаю натуральный ботаник вверх/назад.

Таким образом, я хотел бы использовать различные значки индикаторов, чтобы указать две разные логики: боковая навигация против вверх/назад.

Пожалуйста, не спорьте о мотивации этого. Это состояние. Спасибо.

Ответ 1

int upId = Resources.getSystem().getIdentifier("up", "id", "android");
if (upId > 0) {
    ImageView up = (ImageView) findViewById(upId);
    up.setImageResource(R.drawable.ic_drawer_indicator);
}

Ответ 2

Решение @matthias не работает на всех устройствах. Лучшим решением для изменения homeAsUpIndicator является установка его @null в стиле и изменение ресурса логотипа программно.

Ниже мой код из style.xml

<style name="Theme.HomeScreen" parent="AppBaseTheme">
  <item name="displayOptions">showHome|useLogo</item>
  <item name="homeAsUpIndicator">@null</item>
  <item name="android:homeAsUpIndicator">@null</item>
</style>

В коде вы можете изменить логотип с помощью метода setLogo().

getSupportActionBar().setLogo(R.drawable.abc_ic_ab_back_holo_light); //for ActionBarCompat
getActionBar().setLogo(R.drawable.abc_ic_ab_back_holo_light); //for default actionbar for post 3.0 devices

Также обратите внимание, что Android API 18 имеет методы для редактирования homeAsUpIndicator программно, ссылаться на документацию.

Ответ 3

Хотя этот ответ может достичь ожидаемого поведения, как вы можете прочитать в комментариях ниже: "Этот хак не работает на некоторых устройствах". Я нашел другой способ в соответствии с Adneal answer, который дает мне ключ и особенно правильный способ сделать.

  • Нижний API: используйте id R.id.up, чтобы получить связанный ImageView.

  • API >= 14: получите относительный Parent Home ImageView (android.R.id.home) и извлеките первый дочерний элемент, который является UpIndicator ( android.R.id.up).

Затем этот код фрагмента динамически изменяется UpIndicator:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    // get the parent view of home (app icon) imageview
    ViewGroup home = (ViewGroup) findViewById(android.R.id.home).getParent();
    // get the first child (up imageview)
    ( (ImageView) home.getChildAt(0) )
        // change the icon according to your needs
        .setImageDrawable(getResources().getDrawable(R.drawable.custom_icon_up));
} else {
    // get the up imageview directly with R.id.up
    ( (ImageView) findViewById(R.id.up) )
        .setImageDrawable(getResources().getDrawable(R.drawable.custom_icon_up));
}  

Я не тестировал несколько устройств (поэтому я не уверен, что этот выше код работает для всех устройств), однако это, похоже, отлично работает в API, упомянутых в части обновления здесь.

Примечание. Если вы не делаете разницу между более высокими и более низкими API-интерфейсами, вы получите исключение NullPointerException, потому что R.id.up недоступен в более высоком API, тогда как android.R.id.up недоступен в более низком API.

Ответ 4

Это сработало для меня

getSupportActionBar().setHomeAsUpIndicator(R.drawable.my_home_as_up)

Ответ 5

Я пишу для этого решение. Это не красиво, но работает:

public static ImageView getHomeAndUpIndicator(View decorView) {
    ImageView res = null;

    int upId = Resources.getSystem().getIdentifier("up", "id", "android");
    if (upId > 0) {
        res = (ImageView) decorView.findViewById(upId);
    } else {
        if (android.os.Build.VERSION.SDK_INT <= 10) {
            ViewGroup acbOverlay = (ViewGroup)((ViewGroup)decorView).getChildAt(0);
            ViewGroup abcFrame = (ViewGroup)acbOverlay.getChildAt(0);
            ViewGroup actionBar = (ViewGroup)abcFrame.getChildAt(0);
            ViewGroup abLL = (ViewGroup)actionBar.getChildAt(0);
            ViewGroup abLL2 = (ViewGroup)abLL.getChildAt(1);
            res = (ImageView)abLL2.getChildAt(0);
        } else if (android.os.Build.VERSION.SDK_INT > 10 && android.os.Build.VERSION.SDK_INT < 16) {
            ViewGroup acbOverlay = (ViewGroup)((ViewGroup)decorView).getChildAt(0);
            ViewGroup abcFrame = (ViewGroup)acbOverlay.getChildAt(0);
            ViewGroup actionBar = (ViewGroup)abcFrame.getChildAt(0);
            ViewGroup abLL = (ViewGroup)actionBar.getChildAt(1);
            res = (ImageView)abLL.getChildAt(0);
        } else {
            ViewGroup acbOverlay = (ViewGroup)((ViewGroup)decorView).getChildAt(0);
            ViewGroup abcFrame = (ViewGroup)acbOverlay.getChildAt(1);
            ViewGroup actionBar = (ViewGroup)abcFrame.getChildAt(0);
            ViewGroup abLL = (ViewGroup)actionBar.getChildAt(0);
            ViewGroup abF = (ViewGroup)abLL.getChildAt(0);
            res = (ImageView)abF.getChildAt(0);
        }
    }
    return res;
}

В качестве параметра put: getWindow(). getDecorView()

Тестирование на нескольких устройствах (nexus 7 (4.4.2), галактика samsung s + (2.3.6), yaiu g3 (4.2.2)) и эмуляторы с android 2.3.3 и 4.1.1

Ответ 6

Вот рабочий код

final Drawable upArrow = getResources().getDrawable(R.drawable.ic_arrow_back_black_24dp);
        upArrow.setColorFilter(Color.parseColor("#000000"), PorterDuff.Mode.SRC_ATOP);
        getSupportActionBar().setHomeAsUpIndicator(upArrow);