如何使用Android在应用栏下方创建剪切的导航抽屉?

问题描述 投票:0回答:1

如何使用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/drawerlayout

https://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”。enter image description here

然后,我用GIMP编辑了一些屏幕截图,以说明我真正想要的,如下图所示。应该可以使用“汉堡包图标”来关闭导航抽屉,即使用它进行切换。

enter image description here

下面是用“全高”导航抽屉生成的一些相关文件,我的问题是,如上图所示,要获得“修剪”的导航抽屉,我必须进行哪些更改?


MainActivity.kt

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>

android navigation drawer clipped
1个回答
0
投票
这比我想的要棘手,但是此错误消息帮助我到达了那里:

DrawerLayout必须使用MeasureSpec.EXACTLY测量

这里是

Kotlin解决方案:

  1. 创建一个扩展DrawerLayout类的新类。在onMeasure方法中,为widthMeasureSpec和heightMeasureSpec创建两个新变量,并将它们传递给超类:

    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) } }

  2. 在您的activity_main.xml文件中,更新最外面的标记以使用新的CustomDrawerLayout。将CustomDrawerLayout和NavigationView layout_height更改为此:

    android:layout_height="wrap_content"

  3. 请确保在找到抽屉式布局视图时将其初始化为CustomDrawerLayout类的实例:

    var drawerLayout : CustomDrawerLayout = findViewById(R.id.drawer_layout)

  4. 为了保持操作栏可见,您需要将其添加到CustomDrawerLayout:

    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>

应该这样做。enter image description here
© www.soinside.com 2019 - 2024. All rights reserved.