В реальных проектах нам часто нужно изменить производительность строки состояния в соответствии с разными страницами. Например: изображение шапки страницы располагается под строкой состояния, а строка состояния прозрачна; цвет строки состояния совпадает с цветом строки заголовка; изменяется цвет содержимого строки состояния. Перед этим я написалReact Navigation создает единый пользовательский интерфейс для Android и iOS, в котором кратко рассказывается о некоторых настройках строки состояния Android. Позже я обнаружил, что это не так просто, как я думал, поэтому я дополнил этот блог, В статье более подробно будет представлен контент, связанный со строкой состояния, и как управлять строкой состояния в проекте React Native, чтобы Приложение можно использовать как на платформах iOS, так и на Android, имеет хорошую производительность.
Я загрузил пример кода наGitHub.
Предварительные знания
Перед официальным стартом я представлю некоторые из соответствующих знаний, которые я изучил, и некоторые паве сделаны для следующего содержания.
Строка состояния в iOS
В iOS страница по умолчаниюполноэкранный(Строка состояния не занимает места), содержимое строки состояния по умолчаниютемный. Поскольку страница является полноэкранной, если мы ее не обработаем, содержимое переместится под строку состояния. В то же время, в связи с появлением мобильных телефонов Liu Haiping, таких как iPhone X, изменилась высота строки состояния.20
стал34
. Чтобы решить эту проблему, мы можем вручную установить верхний компонентpaddingTop
(значение зависит от модели) или используйтеSafeAreaView
компоненты.
В iOS нам нужно только решить проблему безопасной области, а затем установить глубину цвета содержимого в соответствии с разными страницами.
Строка состояния в Android
В Android страница по умолчаниюне на весь экран(строка состояния занимает место), содержимое строки состояния по умолчаниюсветлый цвет.
Поддержка строки состояния в Android прошла через несколько версий:
-
Android4.4 (API 19) ~ Android 5.0 (API 21):пройти через
FLAG_TRANSLUCENT_STATUS
Установить страницу в полноэкранный режим и строку состоянияполупрозрачный(светло-серый). -
Android 5.0 (API 21):при условии
droid:statusBarColor
свойства иsetStatusBarColor
Метод используется для установки цвета строки состояния. -
Android 6.0 (API 23):пройти через
SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
Поддержка настройки содержимого строки состояния кактемный.
Среди них, если вы хотите установить цвет строки состояния, вы не можете установитьFLAG_TRANSLUCENT_STATUS
.
В приложении для Android каждому действию соответствует строка состояния. Это означает, что установка строки состояния для одной страницы не повлияет на строку состояния других страниц.
Строка состояния в React Native
React Native официально предоставляетStatusBar
Компонент используется для управления строкой состояния и поддерживает настройку темного и светлого цвета содержимого, фона строки состояния (Android) и т. д.
StatusBar
Одновременно можно добавить несколько свойств, а свойства объединяются в порядке загрузки (последнее переопределяет первое).
В отличие от строки состояния в Android, строка состояния в React Native является общедоступной, и изменение строки состояния в любом месте приведет к изменению строки состояния, даже если вы переключитесь на другие страницы, которые не установлены. Поэтому нам нужно установить соответствующую строку состояния при рендеринге каждой страницы или сбросить строку состояния при выходе со страницы с установленной строкой состояния.
фактический случай
Обладая необходимыми знаниями, давайте пройдемся по реальному кейсу, чтобы увидеть, что нам нужно сделать и как это сделать лучше.
В данном случае есть три страницы: Home, My и Login. Где «Главная» и «Мои» — две вкладки, заголовок «Главная» имеет фоновое изображение, верхняя часть страницы «Моя» — синяя, а верхняя часть страницы «Вход» — белая. Эффект страницы показан ниже.
Страницы «Домашняя» и «Мои» используют настраиваемый заголовок, который получает высоту строки состояния в соответствии с текущим устройством:
const STATUS_BAR_HEIGHT = isiOS() ? (isiPhoneX() ? 34 : 20) : StatusBar.currentHeight
Среди них для оценки устройства используются следующие методы:
// iPhone X、iPhone XS
const X_WIDTH = 375;
const X_HEIGHT = 812;
// iPhone XR、iPhone XS Max
const XSMAX_WIDTH = 414;
const XSMAX_HEIGHT = 896;
const DEVICE_SIZE = Dimensions.get('window');
const { height: D_HEIGHT, width: D_WIDTH } = DEVICE_SIZE;
export const isiOS = () => Platform.OS === 'ios'
export const isiPhoneX = () => {
return (
isiOS() &&
((D_HEIGHT === X_HEIGHT && D_WIDTH === X_WIDTH) ||
(D_HEIGHT === X_WIDTH && D_WIDTH === X_HEIGHT)) ||
((D_HEIGHT === XSMAX_HEIGHT && D_WIDTH === XSMAX_WIDTH) ||
(D_HEIGHT === XSMAX_WIDTH && D_WIDTH === XSMAX_HEIGHT))
);
};
После получения высоты строки состояния, в зависимости от того, является ли она в настоящее время полноэкранной (fullSreen
собственностьtrue
или устройства iOS), чтобы установить собственную высоту иpaddingTop
, высота строки заголовка равномерно установлена на44
.
const headerStyle = [
styles.header,
(fullScreen || isiOS()) && {
height: STATUS_BAR_HEIGHT + HEADER_HEIGHT,
paddingTop: STATUS_BAR_HEIGHT
}
]
Заголовок страницы «Вход»react-navigation
Компонент заголовка по умолчанию, в Android высота заголовка установлена на56
.
Проблемы со строкой состояния
Из приведенного выше случая можно найти следующие проблемы:
- На устройствах iOS цвет содержимого строки состояния отображается неправильно, строки состояния «Главная» и «Моя» страница должны бытьсветлый цвет.
- На устройствах Android строка состояния «Дом» должна быть прозрачной, а изображение должно выходить за строку состояния.
- На устройствах Android цвет строки состояния «Моя страница» также должен быть синим.
Чтобы приложение работало лучше, нам нужно динамически настраивать строку состояния в соответствии со страницей. React Native предоставляет разработчикамStatusBarкомпонент для управления строкой состояния.
Компонент StatusBar управляет строкой состояния.
На «Домашней странице» мы установили для содержимого строки состояния значение «Светлый», а цвет фона был прозрачным.translucent
дляtrue
. Затем добавляются заголовки обеих страниц «Домашняя» и «Моя».fullScreen
Атрибуты. Эффект следующий:
Как видно из рисунка, поскольку маршрутизация страниц выполняется слоем js, все приложение соответствует одномуStatusBar
, хотя ни на страницах «Мои», ни на «Входе» не установлена строка состояния, но строка состояния также прозрачна.
Таким образом, возникает проблема.Страница «Вход» может фактически использовать эффект по умолчанию, но поскольку строка состояния установлена на других страницах, эффект при входе на страницу «Вход» неправильный. Поэтому для каждой страницы необходимо установить соответствующую строку состояния, потому что строка состояния может быть изменена другими страницами.
Затем установите для строки состояния белый цвет, а для содержимого — темный цвет на странице входа:
<StatusBar translucent={false} backgroundColor='#fff' barStyle="dark-content" />
Теперь страница «вход» работает как положено, когда мы вернемся со страницы «вход» в основной интерфейс, строка состояния переключится обратно в предыдущее состояние, но с небольшой задержкой. Как правило, при возврате со страницы входа строка состояния должна оставаться белой с темным содержимым. Так как предыдущая страница не будет перерисовываться при возврате, строка состояния должна оставаться в своем текущем состоянии. Но строка состояния автоматически настраивается на предыдущее состояние, хотя и с небольшой задержкой. я здесьreact-navigation
изGitHub issueнашел было упомянуто, что при выходеroute
, строка состояния автоматически сбрасывается. Я специально не исследовал, но согласен, что-то подобное должно быть где-то сделано.
Так почему же задержка? Я предполагаю, что это связано со временем автоматического сброса строки состояния. Я попытался добавить страницу регистрации (вход осуществляется нажатием кнопки на странице входа) и установить красный цвет строки состояния. Затем я прослушал на странице входаwillFocus
а такжеdidFocus
событие, соответственно, в обработчике события установите строку состояния в белый цвет. Результат в том, что вwillFocus
Обработка - это то, что мы ожидаем результатов, а такжеdidFocus
Средняя обработка такая же, как и без обработки по умолчанию.
Здесь мы можем сделать основной вывод:Если мы хотим настроить строку состояния в приложении, безопасно делать это на каждой странице.willFocus
При настройке соответствующей строки состояния, если вы не можете убедиться, что строка состояния предыдущей страницы такая же, как и она сама.
Поскольку эта функциональность настолько универсальна, мы можем сделать это с помощью компонента более высокого порядка:
import React from 'react'
import hoistNonReactStatics from 'hoist-non-react-statics'
import { StatusBar } from 'react-native'
import { isAndroid } from '../../utils/device'
export const setStatusBar = (statusbarProps = {}) => WrappedComponent => {
class Component extends React.PureComponent {
constructor(props) {
super(props)
this._navListener = props.navigation.addListener('willFocus', this._setStatusBar)
}
componentWillUnmount() {
this._navListener.remove();
}
_setStatusBar = () => {
const {
barStyle = "dark-content",
backgroundColor = '#fff',
translucent = false
} = statusbarProps
StatusBar.setBarStyle(barStyle)
if (isAndroid()) {
StatusBar.setTranslucent(translucent)
StatusBar.setBackgroundColor(backgroundColor);
}
}
render() {
return <WrappedComponent {...this.props} />
}
}
return hoistNonReactStatics(Component, WrappedComponent);
}
Использовать декоратор тоже очень просто:
@setStatusBar({
barStyle: 'light-content',
translucent: true,
backgroundColor: 'transparent'
})
export default class Home extends React.PureComponent {
...
}
Установить прозрачность полноэкранного режима Android и строки состояния
Помимо прохождения через слой jsStatusBar
Компонент устанавливает цвет, прозрачность и т. д. строки состояния.Мы также можем установить строку состояния Android в полноэкранный режим, а строку состояния сначала сделать прозрачной, чтобы производительность Android была такой же, как у iOS, которая можно обрабатывать единообразно.
существуетMainActivity.java
Добавьте следующий код в , вы можете сделать полноэкранный режим и строку состояния прозрачными:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
}
Эффект после завершения настройки показан на рисунке ниже (без обработкиpaddingTop
).
Теперь покажите строку состояния на Android и iOS же, когда рассматриваются в соответствии с единой логикой обработки для iOS, но высота заголовка иpaddingTop
Разные расчеты.
Вам тоже нужно вниманиеreact-native
Заголовок не обрабатывает полный экран Android, поэтому нам нужно модифицировать его под платформу Android.headerStyle
:
defaultNavigationOptions: {
headerStyle: {
...Platform.OS === 'android' && {
height: StatusBar.currentHeight + 44,
paddingTop: StatusBar.currentHeight
}
}
}
Суммировать
Чтобы строка состояния работала лучше в React Native, все еще нужно поработать. Теперь кажется, что он используетStatusBar
Компоненты проще, потому что даже если полноэкранные и прозрачные статус-бары настроены на родном уровне Android, вам все равно нужно установить цвет содержимого статус-бара в соответствии со страницей, поэтому на js унифицированным образом, с помощью высокоуровневых компонентов Не слишком много проблем.