如何使用Android在应用栏下方创建剪切的导航抽屉?
最新的Android Studio(3.5.3)会生成一个全高的导航抽屉,我的问题是要更改为获取裁剪的导航抽屉,需要更改什么?
(请不要通过链接到带有古老答案的一长串的ANCIENT(例如2015)问题来将此问题标记为“重复”。现在是2020年,我希望现在将存在一种实现裁剪的导航抽屉的简便方法。希望现在有一个简单的解决方案,可以与androidx和jetpack导航以及诸如setupActionBarWithNavController之类的Kotlin方法配合使用。当我上面提到使用Android Studio生成的代码时,我现在在谈论的是Android Studio 3.5.3(即当前的最新版本),以及其带有Kotlin和最低API级别19(即Android 4.4)的项目模板“导航抽屉活动”。当今天的开发人员想要找到一种方法来执行此操作,并使用google和stackoverflow搜索时,我们就不想在具有很多旧/过时页面答案的长页面中查找和滚动。由于这个问题现在是在2020年2月提出的,因此每个人都清楚,下面所有可能出现的答案也将晚于此。)
奇怪的是,很难找到有关如何使用Android实现裁剪抽屉的文档。这里提到了导航抽屉的两种类型(“全高”和“修剪”):
https://material.io/components/navigation-drawer/#standard-drawer
报价:
“标准导航抽屉可以使用以下任一海拔位置:
At the same elevation as a top app bar (full-height) At a lower elevation than a top app bar (clipped)"
在上述网页上,还有指向android特定页面的链接:
https://material.io/develop/android/components/navigation-view/
但是,该页面目前未提及有关如何创建剪辑的导航抽屉的任何内容。另外,该android页面的更新程度似乎不高,因为它目前已链接至有关DrawerLayout的旧支持v4库。
[当我改为查看有关DrawerLayout的新androidx页面时,我仍然找不到有关“裁剪”抽屉的任何内容。(由于“已剪裁”是google的材料设计中使用的术语,因此google也应使用相同的单词在文档页面中进行搜索)。
在某些页面上,[[应该可以找到有关“剪辑”的内容,但不幸的是,目前没有:
https://developer.android.com/jetpack/androidx/releases/drawerlayouthttps://developer.android.com/guide/navigation/navigation-ui#add_a_navigation_drawer
为了说明我要寻找的内容(独立于上面的材料设计页面,可能会有所变化,下面提供一些图片。
[下面的第一张屏幕截图是使用Android Studio 3.5.3(当前是最新的)并使用Kotlin和最低API级别19生成的“ Navigation Drawer Activity”(具有两个修改,请参见下文)。 Android 4.4)。
我已经完成的两个更改(在“ activity_main.xml中”)是我从NavigationView中删除了app:headerLayout,并用android:layout_height =“ wrap_content”替换了android:layout_height =“ match_parent”。
然后,我用GIMP编辑了一些屏幕截图,以说明我真正想要的,如下图所示。应该可以使用“汉堡包图标”来关闭导航抽屉,即使用它进行切换。
下面是用“全高”导航抽屉生成的一些相关文件,我的问题是,如上图所示,要获得“修剪”的导航抽屉,我必须进行哪些更改?
package com.myapplication
import android.os.Bundle
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.navigation.NavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.view.Menu
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val fab: FloatingActionButton = findViewById(R.id.fab)
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
R.id.nav_tools, R.id.nav_share, R.id.nav_send
), drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.google.android.material.navigation.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:menu="@menu/activity_main_drawer" /> </androidx.drawerlayout.widget.DrawerLayout>
app_bar_main.xml
<?xml version="1.0" encoding="utf-8"?> <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:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </com.google.android.material.appbar.AppBarLayout> <include layout="@layout/content_main" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" app:srcCompat="@android:drawable/ic_dialog_email" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/app_bar_main"> <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/mobile_navigation" /> </androidx.constraintlayout.widget.ConstraintLayout>
DrawerLayout必须使用MeasureSpec.EXACTLY测量
这里是
Kotlin解决方案:
class CustomDrawerLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : DrawerLayout(context, attrs, defStyleAttr) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec),MeasureSpec.EXACTLY)
var newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),MeasureSpec.EXACTLY)
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec)
}
}
android:layout_height="wrap_content"
var drawerLayout : CustomDrawerLayout = findViewById(R.id.drawer_layout)
android:keepScreenOn="true"
这到NavigationView组件:
android:layout_marginTop="?android:attr/actionBarSize"
完整的activity_main.xml文件如下所示:
<com.mullr.neurd.Miscellaneous.CustomDrawerLayout android:id="@+id/clipped_drawer_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:keepScreenOn="true" tools:openDrawer="start" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="wrap_content" /> <com.google.android.material.navigation.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="start" android:layout_marginTop="?android:attr/actionBarSize" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> </com.mullr.neurd.Miscellaneous.CustomDrawerLayout>
应该这样做。