Как найти строку состояния в xml

Время на прочтение
7 мин

Количество просмотров 39K

image
Статья рассказывает о том как работать со строкой состояния в Android. Статья рассчитана на начинающих программистов под Android только осваивающих разработку под платформу. Также стоит заметить что строка состояния в большей степени используется для уведомления пользователя о каких либо событиях произошедших в системе, что по целевой задаче роднит её со всплывающими уведомлениями Toast. На Хабрахабре уже имеется достаточно полная статья о работе с Toast, и данный пост лишь развивает тему уведомлений.

Сам текст статьи писался для песочницы, и по сути Hello world как он есть. Сейчас меня интересует интересно ли вообще кому либо это направление, или же оно того не стоит.

Кратко о строке уведомления

На первом скриншоте представлена раскрытая строка состояния в стандартной оболочке Android (некоторые производители мобильных устройств в своих оболочках могут изменить её внешний вид, хотя суть остаётся той же). Строка состояния в Android по большей части используется для уведомления пользователя о каких либо событиях произошедших в системе, а также о результатах работы каких либо приложений. Существенным отличием от всплывающих уведомлений Toast является то что уведомления в строке состояния не пропадают спустя время, и «висят» там до тех пор пока пользователь как-то на них отреагирует. Строку состояния удобно использовать для получения уведомлений от приложений запущенных в фоновом режиме, а также с появлением уведомления можно проиграть какой либо звук, вибрацию, или же воспользоваться мигающими индикаторами на устройстве (если они имеются). Уведомление представленное на скриншоте — именно то чего сегодня мы и будем добиваться.

Создание простого уведомления в строке состояния

Для начала попробуем создать стандартное уведомление для командной строки так как это рекомендуют в Google. Разметку интерфейса приложения оставим без изменений (уведомление будет появляться сразу после его запуска). И так, пример кода (с комментарием того что возможно может быть не ясным):

public class NotificationBar extends Activity {
  /** Called when the activity is first created. */private static final int NOTIFY_ID = 1; // Уникальный индификатор вашего уведомления в пределах класса
  @Overridepublic void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // Создаем экземпляр менеджера уведомлений
    int icon = android.R.drawable.sym_action_email; // Иконка для уведомления, я решил воспользоваться стандартной иконкой для Email
    CharSequence tickerText = "Hello Habrahabr"; // Подробнее под кодом
    long when = System.currentTimeMillis(); // Выясним системное время
    Notification notification = new Notification(icon, tickerText, when); // Создаем экземпляр уведомления, и передаем ему наши параметры
    Context context = getApplicationContext(); 
    CharSequence contentTitle = "Habrahabr"; // Текст заголовка уведомления при развернутой строке статуса
    CharSequence contentText = "Пример простого уведомления"; //Текст под заголовком уведомления при развернутой строке статуса
    Intent notificationIntent = new Intent(this, NotificationBar.class); // Создаем экземпляр Intent
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);class); // Подробное описание в UPD к статье
    notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); // Передаем в наше уведомление параметры вида при развернутой строке состояния
    mNotificationManager.notify(NOTIFY_ID, notification); // И наконец показываем наше уведомление через менеджер передав его ID
  }
}

* This source code was highlighted with Source Code Highlighter.

CharSequence tickerText = «Hello Habrahabr»; — в этой строке мы указываем текст который будет показан в свёрнутой строке состояния на несколько секунд при появлении уведомления. Спустя несколько секунд он исчезнет, а в строке останется лишь иконка.

Вот пожалуй и всё. Можно открывать шампанское, и наблюдать то что у нас получилось.

image

Создание расширенного уведомления в строке состояния

Теперь несколько усложним задачу — мы будем создавать уведомление не по шаблону что предлагает Google, а по собственной разметке (благо такая возможность имеется). И так создадим новый файл разметки в папке layout, у вас он должен получиться таким:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:orientation="horizontal"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:padding="3dp"
       >
  <ImageView android:id="@+id/image"
       android:layout_width="wrap_content"
       android:layout_height="fill_parent"
       android:layout_marginRight="10dp"
       />
  <TextView android:id="@+id/text"
       android:layout_width="wrap_content"
       android:layout_height="fill_parent"
       android:textColor="#000"
       />
</LinearLayout>
* This source code was highlighted with Source Code Highlighter.

Также добавим какую либо картинку в папку drawable дабы потом установить её в ImageView.

Теперь код. Код не сильно отличается от кода простого уведомления, но тем не менее требует комментария

public class NotificationBar extends Activity {
  /** Called when the activity is first created. */private static final int NOTIFY_ID = 1; // Уникальный индификатор вашего уведомления в пределах класса
  @Overridepublic void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // Создаем экземпляр менеджера уведомлений
    int icon = android.R.drawable.sym_action_email; // Иконка для уведомления, я решил воспользоваться стандартной иконкой для Email
    CharSequence tickerText = "Hello Habrahabr"; // Подробнее под кодом
    long when = System.currentTimeMillis(); // Выясним системное время
    Intent notificationIntent = new Intent(this, NotificationBar.class); // Создаем экземпляр Intent
    Notification notification = new Notification(icon, tickerText, when); // Создаем экземпляр уведомления, и передаем ему наши параметры
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); // Подробное описание смотреть в UPD к статье
    RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.notlayout); // Создаем экземпляр RemoteViews указывая использовать разметку нашего уведомления
    contentView.setImageViewResource(R.id.image, R.drawable.habr); // Привязываем нашу картинку к ImageView в разметке уведомления
    contentView.setTextViewText(R.id.text,"Привет Habrahabr! А мы тут, плюшками балуемся..."); // Привязываем текст к TextView в нашей разметке
    notification.contentIntent = contentIntent; // Присваиваем contentIntent нашему уведомлению
    notification.contentView = contentView; // Присваиваем contentView нашему уведомлению
    mNotificationManager.notify(NOTIFY_ID, notification); // Выводим уведомление в строку
    }
}
* This source code was highlighted with Source Code Highlighter.

В итоге можем открывать вторую бутылку, и наблюдать примерно такую картину:

image

Добавляем звук и вибрацию, мигаем индикаторами.

Для пущей важности добавим звук при выводе уведомления и вибрацию. Сделать это совсем не сложно.

notification.defaults |= Notification.DEFAULT_SOUND; — данная строка присваивает уведомлению звук что используется в системе по умолчанию.
notification.sound = Uri.parse(«file:///sdcard/notification/ringer.mp3»); — таким способом можно установить звук из файла на SD карте.

notification.defaults |= Notification.DEFAULT_VIBRATE; — данная строка добавляет вибрацию в колличестве времени по умолчанию.

Кроме того имеется возможность задать время вибрации самостоятельно. Делается это двумя строчками
long[] vibrate = {0,100,200,300}; — создаем массив, в котором 1-ое число — время которое следует подождать до того как запустить вибрацию. Второе значение — время первой вибрации в миллисекундах (аналогично и 3, и 4 значение). Количество вибраций может быть бесконечно большим по усмотрению программиста.
notification.vibrate = vibrate; — присваиваем массив нашему уведомлению.

notification.defaults |= Notification.DEFAULT_LIGHTS; — данной строкой мы можем по мигать индикаторами с параметрами по умолчанию.

Конечно можно настроить параметры и в ручную.Для этого нам потребуется 4 строки:
notification.ledARGB = 0xff00ff00; — задаем цвет для RGB индикатора.
notification.ledOnMS = 300; — задаем время между миганиями
notification.ledOffMS = 1000; — задаем время спустя которое горящий индикатор потухнет
notification.flags |= Notification.FLAG_SHOW_LIGHTS; — разрешаем мигать
Тут следует заметить что далеко не на всех девайсах вообще имеются какие либо индикаторы.

Естественно все эти установки нужно производить до строчки вызова уведомления.

Заключение

Вот пожалуй и всё. Пост никак не претендует на полноту, и всё же данной информации должно быть вполне достаточно новичкам. В качестве источника, а также более полного описания работы с NotificationBar могу привести оригинальную статью на developer.android.com. Надеюсь статья поможет кому либо в изучении возможностей платформы. Спасибо за внимание.

UPD

: при внимательном рассмотрении выяснилось что комментарий к одной из строчек кода отсутствует (обещается объяснить под кодом, но самого объяснения нет). Досадную ошибку исправляет, а также ряд ф-и строки состояния о которых я сообщить забыл восполняет пользователь djvu, взглянуть можно в комментариях: 1, 2. О существовании серьезных подводных камней сообщает sdmitry вот тут.

I am getting a response from a web service call in XML format. I want to search for the status string in the XML response and proceed further depending on its value. How can I do this? The response is below:

<META NAME="ColdFusionMXEdition" CONTENT="ColdFusion DevNet Edition - Not for Production Use."><?xml version="1.0" encoding="UTF-8"?>
<ParticipantService>
    <Response>
        <student_id>10082</student_id>
    </Response>
    <RequestStatus>
        <Code>1</Code>
        <Status>SUCCESS</Status>
        <Message>Valid Credentials.</Message>
    </RequestStatus>
</ParticipantService>

Pops's user avatar

Pops

30k37 gold badges134 silver badges151 bronze badges

asked Mar 21, 2012 at 10:13

Pradeep Reddy Kypa's user avatar

You can use NSXmlParser. If you are checking only for status you can do some string manipulation as follows,

NSString *mystring = @"<Response><status>SUCCESS</status> </Response>";
NSString *neededString = nil;
NSScanner *scanner =[NSScanner scannerWithString:mystring];
[scanner scanUpToString:@"<status>" intoString:NULL];
[scanner scanString:@"<status>" intoString:NULL];
[scanner scanUpToString:@"</status>" intoString:&neededString];
NSLog(@"%@",neededString);
if ([neededString isEqualToString:@"SUCCESS"]){  //do what you like. }

answered Mar 21, 2012 at 10:31

Vignesh's user avatar

0

Do you have access to XPath in your development libraries ?

If so, you could use (e.g.);

if (myDoc.xPath('/RequestStatus[Status = "SUCCESS"]').size() > 0) {  }

answered Mar 21, 2012 at 10:19

Marius's user avatar

MariusMarius

2,9931 gold badge15 silver badges24 bronze badges

Иммерсивная строка состояния Android

  • Предисловие
    • Версия Android
    • До Android4.4
    • Android4.4(API 19) — Android 5.0(API 21)
      • 1. Погружение в картинку
        • 1.1 реализация xml
        • 1.2 реализация кода
      • 2. погружение в инструментальную панель
        • 2.1xml реализация
          • 2.1.1 Установить свойство fitsSystemWindows
          • 2.1.2 Добавление строки состояния заполнителя в макет
        • 2.2 Реализация кода
          • 2.2.1 Код устанавливает свойство fitsSystemWindows
          • 2.2.2 Добавление строки состояния заполнителя в макет
    • Разница между Android4.4 (API 19) и Android 5.0 (API 21)
    • Android 5.0(API 21)
      • 1. Погружение в картинку
      • 2. погружение в инструментальную панель
    • Android 6.0
    • подводить итоги
    • Инструменты, написанные самостоятельно

Предисловие

Недавно я изучал иммерсивную строку состояния Android и читал много домашних блогов, и они очень беспорядочные. Здесь я обобщу свой опыт. Эта статья будет основана наВерсия Androids разница,Метод реализацииРазные (реализация xml, реализация кода) иРеализуйте функциюРазличия (изображение погружено, строка состояния и строка заголовка имеют одинаковый цвет) объясняются отдельно.

Версия Android

Android4.4(API 19) — Android 5.0(API 21): Погружение может быть достигнуто на этом этапе, но производительность не очень хорошая.Реализация такова: установите строку состояния в прозрачный и полноэкранный режим с помощью FLAG_TRANSLUCENT_STATUS, а затем, добавив View того же размера, что и StatusBar, установите нам фон View Цвет, которым вы хотите добиться погружения.
Android 5.0 (API 21) и выше: В Android 5.0 был добавлен важный атрибут и метод android: statusBarColor (соответствующий метод — setStatusBarColor), с помощью этого метода мы можем легко достичь погружения. Другими словами, начиная с Android 5.0 система действительно поддерживает погружение.
Android 6.0 (API 23) и выше: Собственно, способ реализации выше Android 6.0 такой же, как и в Android 5.0+. Почему это должно быть выделено в отдельный важный этап? Это связано с тем, что начиная с Android 6.0 (API 23) мы можем изменить режим рисования строки состояния, которая может отображать белый или светло-черный контент и значки (за исключением телефонов Meizu, Meizu имеет собственные изменения исходного кода, которые могут быть достигнуты в версии 6.0).

До Android4.4

До Android 4.4 наше приложение не могло изменить цвет строки состояния телефона. Когда мы открываем приложение, появляется экран слева на рисунке выше. В верхней части экрана есть черная строка состояния, а стиль приложения очень Не согласовано.

Android4.4(API 19) — Android 5.0(API 21)

После Android 4.4 поддерживается иммерсивная строка состояния, но она немного отличается от таковой после Android 5.0.

1. Погружение в картинку

Эффект такой:

1.1 реализация xml

<style name="NewStyle" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowTranslucentStatus"> true </item> Строка состояния системы прозрачна
    <item name="android:windowTranslucentNavigation"> true </item> Панель навигации системы прозрачна, что выходит за рамки этой статьи и может быть опущено.
</style>

В результате макет заполнит строку состояния и панель навигации! Как показано слева:


Если вы не хотите, чтобы изображение отображалось в строке состояния, вы можете добавить его в корневой макет.android:fitsSystemWindows=»true»
Этот атрибут заставляет макет системы учитывать положение макета системы (строка состояния, панель навигации и т. д.), поэтому строка состояния и панель навигации не будут заблокированы. Строка состояния и панель навигации будутМакет корня того же цветаВ это время тоже теряет смысл погружения картинки.Данный способ подходит для панели инструментов.

1.2 реализация кода

/**
           * Установить цвет строки состояния
     *
           * @param activity Активность, которую нужно установить
           * @param color значение цвета строки состояния
     */
    public static void setTranslucentStatus(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
        &&Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {// Определяем, старше ли версия Android 4.4
            // Сделать строку состояния прозрачной
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            // Устанавливаем корневой макет android: fitsSystemWindows = "true, добавлять не нужно
            ViewGroup rootView = (ViewGroup) ((ViewGroup)activity.findViewById(android.R.id.content)).getChildAt(0);
            rootView.setFitsSystemWindows(true);

2. погружение в инструментальную панель

Из вышесказанного картинка погружена в строку состояния. Но иногда, например, когда включена ToolBar, мы не хотим погружать макет Toolbar в строку состояния, потому что это заставит строку состояния закрывать ToolBar, как показано слева. Мы надеемся, что панель инструментов и строка состояния будут одного цвета, как показано справа.

2.1xml реализация

2.1.1 Установить свойство fitsSystemWindows

Установить в корневом макетеandroid:fitsSystemWindows=»true, Чтобы строка состояния была того же цвета, что и корневой макет, и цель может быть достигнута путем установки цвета макета таким же, как у ToolBar.Но у этого способа есть проблемыНапример, если мы хотим установить для строки состояния синий цвет, это может быть достигнуто только путем установки синего фона самого внешнего макета. Однако после настройки весь макет станет синим, что может быть только в содержимом макета ниже. Кроме того, установите белый фон, и таким образом будет перерисовка.Так что это не рекомендуется!

2.1.2 Добавление строки состояния заполнителя в макет

Добавьте строку состояния заполнителя в корневой макет, чтобы, хотя вся страница содержимого располагалась сверху вниз, поскольку в макет содержимого добавляется строка состояния заполнителя, эффект был таким же, как и ожидалось.

<View
  android:id="@+id/statusBarView"
  android:background="@color/blue"  Установите цвет строки состояния
  android:layout_width="match_parent"
  android:layout_height="wrap_content">    Установите высоту строки состояния
  </View>

2.2 Реализация кода

2.2.1 Код устанавливает свойство fitsSystemWindows
/**
 * Установите свойство FitsSystemWindows самого внешнего макета страницы.
* @param activity
* @param value
*/
public static void setFitsSystemWindows(Activity activity, boolean value) {
  ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
  View parentView = contentFrameLayout.getChildAt(0);
  if (parentView != null && Build.VERSION.SDK_INT >= 14) {
      parentView.setFitsSystemWindows(value);
  }
}

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

2.2.2 Добавление строки состояния заполнителя в макет

Получите высоту строки состояния через отражение:

/**
* Используйте отражение, чтобы получить высоту строки состояния
* @return
*/
public int getStatusBarHeight() {
  int result = 0;
  // Получаем идентификатор ресурса высоты строки состояния
  int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
  if (resourceId > 0) {
      result = getResources().getDimensionPixelSize(resourceId);
  }
  return result;
}

Код для добавления представления заполнителя в строке состояния:

/**
   * Добавить заполнитель в строке состояния
 *
 * @param activity
 */
private void addStatusViewWithColor(Activity activity, int color) {
    ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();    
    View statusBarView = new View(activity);
    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            getStatusBarHeight(activity));
    statusBarView.setBackgroundColor(color);
    decorView.addView(statusBarView, lp);
    // decorViewDecorView - это самый верхний вид всего интерфейса Window, который содержит наш android.R.id.content, а также ** макет кадра **. Поскольку это макет фрейма, нам нужно вызвать setFitsSystemWindows, чтобы установить свойство fitsSystemWindows, и добавленное представление будет только полезным! !
    setFitsSystemWindows(activity,true);
}

Информацию о DecorView и android.R.id.content см. Вhttps://www.jianshu.com/p/579e9cc8b83c
https://www.jianshu.com/p/ee7e3b08c23c

Разница между Android4.4 (API 19) и Android 5.0 (API 21)

Использование Android 4.4 также полностью применимо после Android 5.0, но после Android 5.0 это не полностью прозрачная строка состояния, а полупрозрачная строка состояния!

Чтобы сделать настройки Android 4.4 применимыми к Android 5.0 и более поздних версий, добавьте следующий код:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    Window window = getWindow();            
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    window.setStatusBarColor(Color.TRANSPARENT);            
    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    }

Узнаем из следующей статьи, здесь удаленоandroid:fitsSystemWindows=»trueИ добавилandroid:statusBarColor = «@android:color/transparent(Вышесказанное реализовано в коде). Потому что эти два атрибута не могут действовать одновременно. (Android: statusBarColor = «@android: color / transparent — атрибут, предоставляемый после Android 5.0).

Но из-заandroid:windowTranslucentStatusКогда свойство отключено, строка состояния больше не будет плавать в нашем окне. Неважно, мы можем добиться того же эффекта следующими способами:

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

Фактически, при установке атрибута android: windowTranslucentStatus именно система помогла нам установить вышеуказанный флаг;

Мы вызвали этот метод в DecorView выше, но его можно вызвать в любом видимом представлении, и эффект будет таким же. Добавим описание других доступных флагов setSystemUiVisibility:

View.SYSTEM_UI_FLAG_VISIBLE Флаг 14 уровня по умолчанию

View.SYSTEM_UI_FLAG_LOW_PROFILE Level 14
 В режиме низкого энергопотребления значок строки состояния будет скрыт, и в 4.0 можно реализовать полноэкранный режим. Соответствующие значки строки состояния и панели навигации будут ослаблены, например, несколько виртуальных клавиш панели навигации будут превращены в очень маленькие точки. Как только вы снова нажмете на область, где расположены строка состояния и панель навигации, они снова станут полностью видимыми. Преимущество этого метода в том, что строка состояния и панель навигации не исчезли, они остались в интерфейсе, но их детали затемнены и размыты.


View.SYSTEM_UI_FLAG_LAYOUT_STABLE Level 16
 Сохраняйте стабильность всего представления, часто перемещайтесь вместе с панелью, скрывайте и делитесь, чтобы представление не отображалось из-за изменений в SystemUI


View.SYSTEM_UI_FLAG_FULLSCREEN Level 16
 Строка состояния скрыта (панель навигации все еще отображается). Он имеет тот же эффект, что и WindowManager.LayoutParams.FLAG_FULLSCREEN (на самом деле, это другое, потому что высота строки состояния под этим флагом все еще будет существовать, а не полный экран в истинном смысле). В то же время, при использовании FEATURE_ACTION_BAR_OVERLAY панели действий, включение SYSTEM_UI_FRELAR скроет этот ActionBar; Логотипы обычно подходят для краткосрочного полноэкранного режима, а не для долгосрочного.


View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN Level 16
 Строка состояния плавает при Активности


View.SYSTEM_UI_FLAG_HIDE_NAVIGATION Level 14
 Временно скрыть панель навигации. Из-за важности панели навигации при малозаметном взаимодействии пользователя, например при нажатии на экран, панель навигации может снова появиться. Это связано с тем, что система сбрасывает флажок и флаг SYSTEM_UI_FLAG_FULLSCREEN, который используется вместе с флагом SYSTEM_UI_FLAG_IMMERSIVE. Можно избежать очистки


View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION Level 16
 Панель навигации перемещается по Activity


View.SYSTEM_UI_FLAG_IMMERSIVE Level 19
 Недавно добавленный в Kitkat флаг, иммерсивный режим, имеет смысл при использовании вместе с SYSTEM_UI_FLAG_HIDE_NAVIGATION. Он может помешать системе сбросить флаг SYSTEM_UI_FLAG_HIDE_NAVIGATION при незаметном взаимодействии с пользователем. Например, когда логотип SYSTEM_UI_FLAG_HIDE_NAVIGATION используется отдельно, просто щелкните по экрану, и панель навигации снова появится; если логотип используется одновременно, он не появится, но пользователь все равно может активно вызывать в области панели навигации. После вызова соответствующая отметка будет снята.


View.SYSTEM_UI_FLAG_IMMERSIVE_STIKY Level 19
 Необходимо использовать вместе с SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION или SYSTEM_UI_FLAG_FULLSCREEN. Когда указанные выше знаки используются отдельно, любое взаимодействие с пользователем приведет к повторному появлению панели навигации, а при скольжении сверху вниз строка состояния будет повторно вызвана. Эти операции приведут к исчезновению этих знаков. Если одновременно указан флаг SYSTEM_UI_FLAG_IMMERSIVE_STIKY, соответствующий флаг не будет сброшен, и скрытая полоса будет снова автоматически скрыта после вызова

Android 5.0(API 21)

После Android 5.0 Google напрямую предоставляетandroid:statusBarColorСвойства, вы можете напрямую установить цвет строки состояния.

1. Погружение в картинку

Код реализован как:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);  \ Установите этот флаг перед установкой цвета! SetStatusBarColor не может быть установлен со следующим флагом
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    window.setStatusBarColor(Color.TRANSPARENT);// Также может быть реализовано в xml файле
    // Поскольку window.setStatusBarColor (Color.TRANSPARENT) не может заставить исчезнуть строку состояния, необходимо задать следующую строку кода, чтобы макет заполнял строку состояния.
    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}

Этот код похож на приведенный выше.

2. погружение в инструментальную панель

1. Вызовите window.setStatusBarColor (color), чтобы установить цвет строки состояния.
2. Создайте новый стиль в XML-файле, установите атрибут android: statusBarColor и измените цвет строки состояния.

Android 6.0

После Android 6.0 цвет шрифта в строке состояния можно контролировать в соответствии с глубиной цвета строки состояния. Когда строка состояния светлая, шрифт темный для улучшения визуальных эффектов.

1. Реализация XML

<item name="android:windowLightStatusBar">true</item>

Установите светлую строку состояния, и шрифт естественным образом станет темным.

2. Реализация кода

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {             
	getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}

подводить итоги

В этой статье реализованы различные состояния строки состояния в xml и коде. Рекомендуется реализовать это только в коде. Код можно упаковать и использовать повторно. Программисты никогда не изобретают колеса, и в той же иммерсивной строке состояния уже есть колеса, см.StatusBarUtil!
Первый блог, готов!

Инструменты, написанные самостоятельно

Эффект от внедрения чужих пакетов не очень хороший, поэтому я написал инструмент сам. только для справки.


import android.app.Activity;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.v4.graphics.ColorUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;

public class MyStatusBarUtil {

    public static void setTransparent(Activity activity){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.setStatusBarColor(Color.TRANSPARENT);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    public static void setColor(Activity activity,int color){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().setStatusBarColor(color);
            if(isLightColor(color))
                setDarkFont(activity);
        }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            addStatusViewWithColor(activity,color);
            if(isLightColor(color))
                setDarkFont(activity);
        }
    }

    public static void setDarkFont(Activity activity){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }

    }

    /**
           * Используйте отражение, чтобы получить высоту строки состояния
     * @return
     */
    public static int getStatusBarHeight(Activity activity) {
        int result = 0;
        // Получаем идентификатор ресурса высоты строки состояния
        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = activity.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    public static void addStatusViewWithColor(Activity activity, int color) {
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        View statusBarView = new View(activity);
        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                getStatusBarHeight(activity));
        statusBarView.setBackgroundColor(color);
        decorView.addView(statusBarView, lp);
        // decorViewDecorView - это самый верхний вид всего интерфейса Window, который содержит наш android.R.id.content, а также ** макет кадра **. Поскольку это макет фрейма, нам нужно вызвать setFitsSystemWindows, чтобы установить свойство fitsSystemWindows, и добавленное представление будет только полезным! !
        setFitsSystemWindows(activity,true);
    }

    /**
           * Установить внешний вид страницы FitsSystemWindows свойства
     * @param activity
     * @param value
     */
    public static void setFitsSystemWindows(Activity activity, boolean value) {
        ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
        View parentView = contentFrameLayout.getChildAt(0);
        if (parentView != null && Build.VERSION.SDK_INT >= 14) {
            parentView.setFitsSystemWindows(value);
        }
    }

    /**
           * Определите, яркий ли цвет
     *
     * @param color
     * @return
     * @from https://stackoverflow.com/questions/24260853/check-if-color-is-dark-or-light-in-android
     */
    public static boolean isLightColor(@ColorInt int color) {
        return ColorUtils.calculateLuminance(color) >= 0.5;
    }
}

Мне нужно оптимизировать приложение для Android, чтобы хорошо выглядеть на телефонах с надстройкой, например, Essential Phone.

Эти телефоны имеют разную высоту строки состояния, чем стандартное значение 25dp, поэтому вы не можете жестко записать это значение.

Предварительный анонс Android P, выпущенный вчера, включает поддержку метки и некоторых API для запроса ее местоположения и ограничений, но для моего приложения мне нужно только получить высоту строки состояния из XML и не использовать фиксированное значение.

К сожалению, я не смог найти способ получить это значение из XML.

Там в любом случае?

Спасибо.

Перейдя в Java и Android из мира C# .NET так и хочется притащить в чужой монастырь свой устав. В данном случае речь пойдет о декларативных состояниях интерфейса (Visual States). Начнем сразу с простой проблемки: у нас есть вьюшка, на которой отображается профиль какого-то пользователя, но, в зависимости от роли текущего пользователя, эта вьюшка может чуть-чуть отличаться. Допустим, у нас есть три роли: guest, member и moderator, и состояния этой вьюшки будут выглядеть следующим образом:

Описание состояний интерфейса в XML вместо кода для Android - 1

Эти состояния похожи, поэтому будет нелогично делать три разных лэйаута (представим, что реальная вьюшка намного сложнее, но между состояниями больше сходств, чем различий). Как вариант – описать один XML со всеми кнопками и потом кодом менять видимость нужных кнопок для нужных состояний. Вот здесь и приходят на помощь вижуал стейты, которые позволят нам описать эти самые состояния прямо в XML нашей вьюшки без кода. Фактически, код будет делать только goToState(stateName). Так это делают в мире C# + XAML, причем, в специальном редакторе (Blend) можно создавать эти состояния, визуально менять интерфейс (он запомнит изменения для текущего стейта), настраивать переходы между стейтами, добавлять анимации, создавать параллельные стейт машины. Я лишь попытался в стиле proof of concept перенести это в Android на уровне минимального функционала. Вот как будет выглядеть разметка и состояния для нашего примера:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:vs="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical" android:gravity="center_horizontal"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:layout_marginTop="20dp">

    <TextView android:id="@+id/status"
              android:layout_width="wrap_content" android:layout_height="wrap_content"
              android:text="You entered as guest" android:textSize="16sp"
              android:layout_marginBottom="5dp"/>

    <ImageView android:id="@+id/photo"
               android:layout_width="250dp" android:layout_height="250dp"
               android:layout_gravity="center_horizontal" android:src="@drawable/avatar"/>

    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
              android:layout_marginTop="10dp"
              android:text="Vasya Pupkin" android:textSize="20sp" android:textStyle="bold"
              android:layout_marginBottom="20dp"/>

    <Button android:id="@+id/addToFriendsButton"
            android:layout_width="250dp" android:visibility="gone"
            android:layout_height="wrap_content"
            android:text="Add to friends"/>

    <Button android:id="@+id/banButton" android:visibility="gone"
            android:layout_width="250dp"  android:layout_height="wrap_content"
            android:text="Ban"/>

    <ImageButton android:id="@+id/facebookButton" android:visibility="visible"
                 android:layout_width="250dp" android:layout_height="60dp"
                 android:background="@null" android:src="@drawable/fb" android:scaleType="fitXY" />

    <com.eb.vsm.VisualStateManager android:id="@+id/visualStateManager" style="@style/vsm"
            vs:defaultStateName="Guest">

        <!--GUEST state-->
        <com.eb.vsm.VisualState style="@style/vsm" vs:stateName="Guest">
            <com.eb.vsm.SetText style="@style/vsm"
                                vs:targetId="@id/status"
                                vs:text="You entered as guest"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/addToFriendsButton"
                                      vs:visibility="gone"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/banButton"
                                      vs:visibility="gone"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/facebookButton"
                                      vs:visibility="visible"/>
            <com.eb.vsm.SetSrc style="@style/vsm"
                               vs:targetId="@id/photo"
                               vs:src="@drawable/unknown_avatar"/>
        </com.eb.vsm.VisualState>

        <!--MEMBER state-->
        <com.eb.vsm.VisualState style="@style/vsm" vs:stateName="Member">
            <com.eb.vsm.SetText style="@style/vsm"
                                vs:targetId="@id/status"
                                vs:text="You entered as member"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/addToFriendsButton"
                                      vs:visibility="visible"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/banButton"
                                      vs:visibility="gone"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/facebookButton"
                                      vs:visibility="gone"/>
            <com.eb.vsm.SetSrc style="@style/vsm"
                               vs:targetId="@id/photo"
                               vs:src="@drawable/avatar"/>
        </com.eb.vsm.VisualState>

        <!--MODERATOR state-->
        <com.eb.vsm.VisualState style="@style/vsm" vs:stateName="Moderator">
            <com.eb.vsm.SetText style="@style/vsm"
                                vs:targetId="@id/status"
                                vs:text="You entered as moderator"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/addToFriendsButton"
                                      vs:visibility="visible"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/banButton"
                                      vs:visibility="visible"/>
            <com.eb.vsm.SetVisibility style="@style/vsm"
                                      vs:targetId="@id/facebookButton"
                                      vs:visibility="gone"/>
            <com.eb.vsm.SetSrc style="@style/vsm"
                               vs:targetId="@id/photo"
                               vs:src="@drawable/avatar"/>
        </com.eb.vsm.VisualState>

    </com.eb.vsm.VisualStateManager>
</LinearLayout>

Собственно, VisualStateManager – это фэйковый виджет (ViewGroup), который является контейнером именованных стейтов (VisualState), которые в свою очередь являются контейнерами сеттеров. Сеттер — абстрактный класс, с одним методом apply и свойством target. Я описал пяток стандартных сеттеров, но ни что не мешает добавить свои :-).
А когда мы переходим в какое-нибудь состояние – выполнятся все его сеттеры.
Таким образом, в коде чистота и только одинокий вызов stateManage.goToState(“Moderator”) вместо кучи лапши, управляющей свойствами виджетов (хотя по сути, лапша перебралась в XML).

public class MainActivity extends Activity {

    private VisualStateManager visualStateManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        visualStateManager = (VisualStateManager)findViewById(R.id.visualStateManager);

        //init view with "guest" state (it can be done via XML as well)
        visualStateManager.goToState("Guest");

        //go to "moderator" state on FB button click
        ((ImageButton)findViewById(R.id.facebookButton)).setOnClickListener((view) -> {
                visualStateManager.goToState("Moderator");
        });
    }
}

В качестве упреждающего удара комментариям:

Описание состояний интерфейса в XML вместо кода для Android - 2

Повторюсь, это то, чем в мире XAML очень часто пользуются (в основном благодаря хорошей поддержке редактором — Blend), возможно покажется интересной идеей и Android разработчикам.
Ссылка на репозиторий на GitHub с рабочим кодом концепта: тыц.

Автор: Nagg

Источник

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как составить бизнес план на открытие кондитерского магазина
  • Химия как найти число молей
  • Шоп как исправить
  • Как найти вектор приоритетов
  • Как найти аммонит в адыгее

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии