在滑动时移动和调整抽屉布局的内容

14

我刚刚发现了这个应用,并看到了一个自定义的 DrawerLayout 动画。

我猜它首先要截屏,然后在 Activity 中绘制一个自定义的 View,但我不确定,也不知道具体细节。

有人知道如何做吗?

输入图片描述

2个回答

26
您可以在DrawerListeneronDrawerSlide()方法中对DrawerLayout中的内容View进行翻译和缩放。由于内容View本身正在调整大小,而右下角有一个单独的TextView,因此我们将两者都放入另一个持有者ViewGroup中。如果不需要该标签TextView,则可以省略持有者ViewGroup
以下是示例基本DrawerLayout设置:
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#222222">

    <RelativeLayout android:id="@+id/holder"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="#E97411" />

            <ImageView android:id="@+id/main_content"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:background="#EEEEEE"
                android:src="@drawable/ic_launcher" />

        </LinearLayout>

        <TextView android:id="@+id/label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:visibility="gone"
            android:textSize="26dp"
            android:text="My App" />

    </RelativeLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="left"
        android:background="#555555" />

</android.support.v4.widget.DrawerLayout>

这个例子展示了标准的View初始化以及实际执行工作的DrawerListener

public class MainActivity extends AppCompatActivity {

    private static final float END_SCALE = 0.7f;

    private DrawerLayout drawerLayout;
    private NavigationView navigationView;
    private Toolbar toolbar;
    private TextView labelView;
    private View contentView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        navigationView = (NavigationView) findViewById(R.id.navigation_view);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        labelView = (TextView) findViewById(R.id.label);
        contentView = findViewById(R.id.content);

        toolbar.setNavigationIcon(new DrawerArrowDrawable(this));
        toolbar.setNavigationOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (drawerLayout.isDrawerOpen(navigationView)) {
                        drawerLayout.closeDrawer(navigationView);
                    }
                    else {
                        drawerLayout.openDrawer(navigationView);
                    }
                }
            }
        );

        drawerLayout.setScrimColor(Color.TRANSPARENT);
        drawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
                @Override
                public void onDrawerSlide(View drawerView, float slideOffset) {
                    labelView.setVisibility(slideOffset > 0 ? View.VISIBLE : View.GONE);

                    // Scale the View based on current slide offset
                    final float diffScaledOffset = slideOffset * (1 - END_SCALE);
                    final float offsetScale = 1 - diffScaledOffset;
                    contentView.setScaleX(offsetScale);
                    contentView.setScaleY(offsetScale);

                    // Translate the View, accounting for the scaled width
                    final float xOffset = drawerView.getWidth() * slideOffset;
                    final float xOffsetDiff = contentView.getWidth() * diffScaledOffset / 2;
                    final float xTranslation = xOffset - xOffsetDiff;
                    contentView.setTranslationX(xTranslation);
                }

                @Override
                public void onDrawerClosed(View drawerView) {
                    labelView.setVisibility(View.GONE);
                }
            }
        );
    }
}
例子使用了一个 SimpleDrawerListener,但如果使用 ActionBarDrawerToggle,则可以类似地覆盖 onDrawerSlide() 方法。在这种情况下,需要调用 super 方法以保留汉堡菜单箭头的动画效果。
请注意,在 Activity 重新创建期间,DrawerLayout 会保留抽屉的状态,因此在处理方向更改等情况时,您可能需要考虑这一点。

1
谢谢,这个方法可行。如果有人的抽屉在右边而不是左边,只需将 final float xTranslation = xOffset - xOffsetDiff; 更改为 final float xTranslation = xOffsetDiff - xOffset;,其余部分就可以正常工作了。 - Vishwajit Palankar

3

抽屉行为是一个库,使用Android DrawerLayout支持库作为父类【易于迁移】,它在抽屉上提供了额外的行为,如在滑动时移动视图或缩放视图的高度。

如果当前项目使用Android DrawerLayout支持库并且对效果感到有些无聊。那么只需更改布局代码并调用必要的方法来实现动画/效果。

查看github代码

Gradle

dependencies {
   implementation 'com.infideap.drawerbehavior:drawer-behavior:0.1.5'
}

如果Gradle同步失败,你可以在项目级别的Gradle中加入以下代码:

repositories {
 maven{
   url "https://dl.bintray.com/infideap2/Drawer-Behavior"
 }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接