Фон
Я хотел поддержать полноэкранный интерфейс навигации, как показано здесь:
https://medium.com/androiddevelopers/windowinsets-listeners-to-layouts-8f9ccc8fa4d1 https://developer.android.com/guide/navigation/gesturenav
Проблема
Несмотря на то, что все действия моего приложения работали нормально, я неожиданно обнаружил проблемный объект с большими пальцами RecyclerView.
Здесь у меня есть 2 странные проблемы:
- При прокрутке квнизу, последние элементы не отображаются полностью.
В ландшафтном режиме большие пальцы выходят за пределы того места, куда я могу добраться, поэтому они также не доступны. Мало того, но я также могу видеть нормальную полосу прокрутки, и обе исчезают при прокрутке вниз:
Что яЯ пытался
Я пытался применить вставки к различным представлениям, включая отступы и поля, но ничего не помогло.
Кроме того, на некоторых веб-сайтах я видел, что я должен использовать View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
ив некоторых, что мне нужно также добавить View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
. Не помогло.
Вот мой текущий код (проект доступен здесь , так как я думаю, что это ошибка):
MainActivity.kt
class MainActivity : AppCompatActivity(R.layout.activity_main) {
inline fun View.updateMargins(@Px left: Int = marginLeft, @Px top: Int = marginTop, @Px right: Int = marginRight, @Px bottom: Int = marginBottom) {
updateLayoutParams<ViewGroup.MarginLayoutParams> {
this.bottomMargin = bottom
this.topMargin = top
this.leftMargin = left
this.rightMargin = right
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setSupportActionBar(toolbar)
findViewById<View>(android.R.id.content).systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
ViewCompat.setOnApplyWindowInsetsListener(appBarLayout) { _, insets ->
val systemWindowInsets = insets.systemWindowInsets
appBarLayout.updateMargins(
left = systemWindowInsets.left,
top = systemWindowInsets.top,
right = systemWindowInsets.right
)
insets
}
ViewCompat.setOnApplyWindowInsetsListener(recyclerView) { _, insets ->
val systemWindowInsets = insets.systemWindowInsets
recyclerView.updatePadding(
left = systemWindowInsets.left,
bottom = systemWindowInsets.bottom,
right = systemWindowInsets.right
)
insets
}
recyclerView.adapter = object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
init {
setHasStableIds(true)
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
return object : RecyclerView.ViewHolder(
LayoutInflater.from(this@MainActivity).inflate(R.layout.list_item, parent, false)
) {}
}
override fun getItemId(position: Int): Long = position.toLong()
override fun getItemCount(): Int = 100
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder.itemView.imageView.setColorFilter(if (position % 2 == 0) 0xffff0000.toInt() else 0xff00ff00.toInt())
holder.itemView.textView.text = "item $position"
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menu.add("test").setIcon(android.R.drawable.ic_dialog_email).setOnMenuItemClickListener {
true
}.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
return super.onCreateOptionsMenu(menu)
}
}
styles.xml (я использую AppTheme в манифесте в качестве темы)
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppTheme" parent="Theme.MaterialComponents.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:navigationBarColor" tools:targetApi="lollipop">
@android:color/transparent
</item>
<item name="android:statusBarColor" tools:targetApi="lollipop">@color/colorPrimaryDark
</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.MaterialComponents.Dark.ActionBar" />
</resources>
activity_main.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<!--app:popupTheme="@style/AppTheme.PopupOverlay"-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:scrollbars="vertical" app:fastScrollEnabled="true"
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:itemCount="100"
tools:listitem="@layout/list_item" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
line.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/darker_gray" />
<padding
android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
</shape>
line_drawable.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/line" android:state_pressed="true" />
<item android:drawable="@drawable/line" />
</selector>
thumb.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners
android:bottomLeftRadius="44dp" android:topLeftRadius="44dp" android:topRightRadius="44dp" />
<padding
android:paddingLeft="22dp" android:paddingRight="22dp" />
<solid android:color="@color/colorPrimaryDark" />
</shape>
thumb_drawable.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/thumb" android:state_pressed="true" />
<item android:drawable="@drawable/thumb" />
</selector>
Вопросы
- Почему это происходит? Он отлично работал в других местах ...
- Как я могу заставить RecyclerView избегать обоих этих случаев, но разрешить навигационной панели внизу отображать содержимое RecyclerView, поскольку оно прозрачное?
- В каких случаях я должен добавить флаг
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
? Что он делает, чтобы помочь в этих случаях?
РЕДАКТИРОВАТЬ: возможный обходной путь состоит в том, чтобы избежать использования CoordinatorLayout. Это работает хорошо, но я хотел сделать вещи "официальным способом". Вот этот обходной путь:
Вместо CoordinatorLayout я использовал:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
...
И в коде я установил поля и отступы для RecyclerView:
ViewCompat.setOnApplyWindowInsetsListener(recyclerView) { _, insets ->
val systemWindowInsets = insets.systemWindowInsets
recyclerView.updatePadding(
bottom = systemWindowInsets.bottom
)
recyclerView.updateMargins(
left = systemWindowInsets.left,
right = systemWindowInsets.right
)
insets
}