制作自定义滑动菜单并不同于导航抽屉
Making custom sliding menu and different from Navigation Drawer
您可能已经见过 Gmail 等应用程序的侧边导航抽屉。但是你如何制作这样一个带有自定义小部件的抽屉,例如我展示了一个导航抽屉,里面有一些随机放置的小部件:
我想在导航视图中使用 constraintLayout
。基本上,我希望它是一个正常的 layout/view,占据一定比例的屏幕,并有滑入和滑出动画。
编辑
如果你不添加 app:menu=@menu/menu_nav
那么它基本上会崩溃,如果你添加一个空白菜单那么你不能只将 constraintLayout 放在导航菜单中,你必须将 constraintLayout 放在FrameLayout 和....最后它不能正常工作,假设你在 imageView 中使用匹配约束然后图像不显示,虽然硬编码字符串现在没问题,但这并没有真正解决问题观点是动态的。
为了使用自定义布局 NavigationDrawer
,您可以将自定义布局包裹在 NavigationView
中,这样您的布局结构将如下所示:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<!-- MainActivity Layout -->
<include
layout="@layout/activity_main_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- NavigationView -->
<com.google.android.material.navigation.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start">
<!-- Custom NavigationView Layout-->
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
有了它,您可以根据需要自由自定义 NavigationView
布局,例如放置 ConstraintLayout
或您喜欢的任何布局。您还可以像使用普通布局一样添加按钮的侦听器。
这是一个演示,您可以从这里开始,VerticalButton
的学分返回 this tutorial
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ADADAD"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<!-- Main Layout -->
<include
layout="@layout/activity_main_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- NavigationView Layout-->
<com.google.android.material.navigation.NavigationView
android:id="@+id/navView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#666666">
<!-- Header Layout -->
<include
android:id="@+id/include"
layout="@layout/nav_header_main" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#ffff00"
android:onClick="onNavigationButtonClick"
android:text="Button1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include" />
<com.example.android.customnavigationdrawerconstraintlayout.VerticalButton
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="24dp"
android:background="#ffff00"
android:onClick="onNavigationButtonClick"
android:text="Button2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button1" />
<com.example.android.customnavigationdrawerconstraintlayout.VerticalButton
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:background="#ffff00"
android:onClick="onNavigationButtonClick"
android:text="button3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button1" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="64dp"
android:layout_marginLeft="64dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="64dp"
android:layout_marginRight="64dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2"
android:src="@drawable/ic_android" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
activity_main_content.xml(MainActivity布局)
<?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:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar_main"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<TextView
android:id="@+id/tv_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
nav_header_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="180dp"
android:background="@color/colorAccent"
android:gravity="bottom"
android:orientation="vertical"
android:padding="16dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:paddingTop="8dp"
app:srcCompat="@drawable/ic_launcher_foreground" />
</LinearLayout>
垂直按钮
public class VerticalButton extends Button {
final boolean topDown;
public VerticalButton(Context context, AttributeSet attrs) {
super(context, attrs);
final int gravity = getGravity();
if (Gravity.isVertical(gravity) && (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = true;
} else
topDown = false;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected void onDraw(Canvas canvas) {
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if (topDown) {
canvas.translate(getWidth(), 0);
canvas.rotate(90);
} else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
DrawerLayout mDrawerLayout;
NavigationView navView;
Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = findViewById(R.id.drawer);
navView = findViewById(R.id.navView);
toolbar = findViewById(R.id.toolbar_main);
setupDrawer();
}
private void setupDrawer() {
// Show the burger button on the ActionBar
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this,
mDrawerLayout, toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
mDrawerLayout.addDrawerListener(toggle);
toggle.syncState();
}
public void onNavigationButtonClick(View view) {
TextView tvMain = findViewById(R.id.tv_main);
tvMain.setText(((Button) view).getText().toString());
mDrawerLayout.closeDrawer(navView);
switch (view.getId()) {
case R.id.button1:
// Do something with button 1
break;
case R.id.button2:
// Do something with button 2
break;
case R.id.button3:
// Do something with button 3
break;
}
}
}
strings.xml
<resources>
<string name="app_name">Custom NavigationView</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
</resources>
Material 设计依赖性
implementation 'com.google.android.material:material:1.0.0'
预览
您可能已经见过 Gmail 等应用程序的侧边导航抽屉。但是你如何制作这样一个带有自定义小部件的抽屉,例如我展示了一个导航抽屉,里面有一些随机放置的小部件:
我想在导航视图中使用 constraintLayout
。基本上,我希望它是一个正常的 layout/view,占据一定比例的屏幕,并有滑入和滑出动画。
编辑
如果你不添加 app:menu=@menu/menu_nav
那么它基本上会崩溃,如果你添加一个空白菜单那么你不能只将 constraintLayout 放在导航菜单中,你必须将 constraintLayout 放在FrameLayout 和....最后它不能正常工作,假设你在 imageView 中使用匹配约束然后图像不显示,虽然硬编码字符串现在没问题,但这并没有真正解决问题观点是动态的。
为了使用自定义布局 NavigationDrawer
,您可以将自定义布局包裹在 NavigationView
中,这样您的布局结构将如下所示:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<!-- MainActivity Layout -->
<include
layout="@layout/activity_main_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- NavigationView -->
<com.google.android.material.navigation.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start">
<!-- Custom NavigationView Layout-->
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
有了它,您可以根据需要自由自定义 NavigationView
布局,例如放置 ConstraintLayout
或您喜欢的任何布局。您还可以像使用普通布局一样添加按钮的侦听器。
这是一个演示,您可以从这里开始,VerticalButton
的学分返回 this tutorial
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ADADAD"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<!-- Main Layout -->
<include
layout="@layout/activity_main_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- NavigationView Layout-->
<com.google.android.material.navigation.NavigationView
android:id="@+id/navView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#666666">
<!-- Header Layout -->
<include
android:id="@+id/include"
layout="@layout/nav_header_main" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#ffff00"
android:onClick="onNavigationButtonClick"
android:text="Button1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include" />
<com.example.android.customnavigationdrawerconstraintlayout.VerticalButton
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="24dp"
android:background="#ffff00"
android:onClick="onNavigationButtonClick"
android:text="Button2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button1" />
<com.example.android.customnavigationdrawerconstraintlayout.VerticalButton
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:background="#ffff00"
android:onClick="onNavigationButtonClick"
android:text="button3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button1" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="64dp"
android:layout_marginLeft="64dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="64dp"
android:layout_marginRight="64dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2"
android:src="@drawable/ic_android" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
activity_main_content.xml(MainActivity布局)
<?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:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar_main"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<TextView
android:id="@+id/tv_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
nav_header_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="180dp"
android:background="@color/colorAccent"
android:gravity="bottom"
android:orientation="vertical"
android:padding="16dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:paddingTop="8dp"
app:srcCompat="@drawable/ic_launcher_foreground" />
</LinearLayout>
垂直按钮
public class VerticalButton extends Button {
final boolean topDown;
public VerticalButton(Context context, AttributeSet attrs) {
super(context, attrs);
final int gravity = getGravity();
if (Gravity.isVertical(gravity) && (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = true;
} else
topDown = false;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected void onDraw(Canvas canvas) {
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if (topDown) {
canvas.translate(getWidth(), 0);
canvas.rotate(90);
} else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
DrawerLayout mDrawerLayout;
NavigationView navView;
Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = findViewById(R.id.drawer);
navView = findViewById(R.id.navView);
toolbar = findViewById(R.id.toolbar_main);
setupDrawer();
}
private void setupDrawer() {
// Show the burger button on the ActionBar
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this,
mDrawerLayout, toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
mDrawerLayout.addDrawerListener(toggle);
toggle.syncState();
}
public void onNavigationButtonClick(View view) {
TextView tvMain = findViewById(R.id.tv_main);
tvMain.setText(((Button) view).getText().toString());
mDrawerLayout.closeDrawer(navView);
switch (view.getId()) {
case R.id.button1:
// Do something with button 1
break;
case R.id.button2:
// Do something with button 2
break;
case R.id.button3:
// Do something with button 3
break;
}
}
}
strings.xml
<resources>
<string name="app_name">Custom NavigationView</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
</resources>
Material 设计依赖性
implementation 'com.google.android.material:material:1.0.0'
预览