制作自定义滑动菜单并不同于导航抽屉

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'

预览