美文网首页Android-CoordinatorLayout.……
[Android]CoordinatorLayout简介(二)几

[Android]CoordinatorLayout简介(二)几

作者: dafasoft | 来源:发表于2020-12-16 15:12 被阅读0次

    参考资料

    CoordinatorLayout简介(一)CoordinatorLayout的简单使用

    Behavior的基类是CoordinatorLayout#Behavior,先看一下类继承关系:


    image.png

    可以看出,系统默认实现的Behavior大致分类六类:

    • 继承于SwipeDismissBehavor的
    • 继承于ExpandableBehavior的
    • 继承于FloatingActionButton的
    • 继承于ViewOffsetBehavior的
    • BottomSheetBehavior

    我们逐个分析

    SwipeDismissBehavor

    看先文档简介:

    An interaction behavior plugin for child views of CoordinatorLayout to provide support for the 'swipe-to-dismiss' gesture.

    翻译:一个为CoordinatorLayout的子View提供"滑动消失"支持的交互插件

    OK 那我们大概就知道它的作用了

    看下使用方式:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:context="com.dafasoft.MainActivity">
        <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <com.google.android.material.appbar.AppBarLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_behavior="com.google.android.material.behavior.SwipeDismissBehavior">
                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="230dp"
                    app:layout_scrollFlags="scroll|exitUntilCollapsed"
                    android:scaleType="fitXY"
                    android:src="@drawable/yellow_zero"/>
    
                <com.google.android.material.tabs.TabLayout
                    android:id="@+id/tabLayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:background="?attr/colorPrimary"
                    app:tabIndicatorColor="@color/teal_700"
                    app:tabIndicatorHeight="4dp"
                    app:tabSelectedTextColor="#000"
                    app:tabTextColor="#fff"/>
            </com.google.android.material.appbar.AppBarLayout>
    
            <androidx.viewpager.widget.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
        </androidx.coordinatorlayout.widget.CoordinatorLayout>
    </RelativeLayout>
    

    然后运行代码 啪一下闪退了,很快啊!

    发生甚么事了? 怎么回事?

    看下CoordinatorLayout#parseBehavior的部分代码,这个方法的作用是根据我们在xml中设置的layout_behavior来解析成真正的Behavior对象,我们看下其中的部分逻辑:

    try {
                Map<String, Constructor<Behavior>> constructors = sConstructors.get();
                if (constructors == null) {
                    constructors = new HashMap<>();
                    sConstructors.set(constructors);
                }
                Constructor<Behavior> c = constructors.get(fullName);
                if (c == null) {
                    final Class<Behavior> clazz =
                            (Class<Behavior>) Class.forName(fullName, false, context.getClassLoader());
                    c = clazz.getConstructor(CONSTRUCTOR_PARAMS);
                    c.setAccessible(true);
                    constructors.put(fullName, c);
                }
                return c.newInstance(context, attrs);
            } catch (Exception e) {
                throw new RuntimeException("Could not inflate Behavior subclass " + fullName, e);
            }
    

    我们获取Constructor的时候,是获取的一个带参数的Constructor方法,CONSTRUCTOR_PARAMS的值分别是Context和AttributeSet

    因此,假如我们要使用SwipeDismissBehavor,需要自定义一下:

    public class TestSwipeDismissBehavior extends SwipeDismissBehavior {
        public TestSwipeDismissBehavior(Context context, AttributeSet attributes) {
            super();
        }
    }
    

    然后将app:layout_behavior="com.google.android.material.behavior.SwipeDismissBehavior"这一行改为
    app:layout_behavior=".behavior.TestSwipeDismissBehavior"

    看下效果:


    SwipeDismissBehavior1[00_00_03--00_00_23].gif

    官方为我们提供的SwipeDismissBehavior的实现类,有且只有一个BaseTransientBottomBar#Behavior, 它的使用是在SnackBar中

    什么是SnackBar

    Snackbar显示在所有屏幕其它元素之上(屏幕最顶层),同一时间只能显示一个snackbar。

    Snackbar的基本使用很简单,与Toast类似。

    Snackbar.make(view, message_text, duration)
       .setAction(action_text, click_listener)
       .show();
    

    make()方法是生成Snackbar的。Snackbar需要一个控件容器view用来容纳,官方推荐使用CoordinatorLayout来确保Snackbar和其他组件的交互,比如滑动取消Snackbar、Snackbar出现时FloatingActionButton上移。显示时间duration有三种类型LENGTH_SHORT、LENGTH_LONG和LENGTH_INDEFINITE。

    setAction()方法可设置Snackbar右侧按钮,增加进行交互事件。如果不使用setAction()则只显示左侧message。

    Snackbar.make(coordinatorLayout,"这是massage", Snackbar.LENGTH_LONG).setAction("这是action", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this,"你点击了action",Toast.LENGTH_SHORT).show();
         }
     }).show();
    

    效果:


    SnackBar[00_00_01--00_00_08].gif

    ExpandableBehavior

    看下官方文档


    image.png

    过期了...使用MaterialContainerTransform替代了

    pass吧...

    FloatingActionButton#Behavior

    这个Behavior官方是给FloatingActionButton特供的

    我们看一下FloatingActionButton吧

    FloatingActionButton是5.0版本出现的控件,显示一个圆形悬浮按钮。需要添加Design依赖库(现在已迁移至Androidx中)并且使用Theme.AppCompat主题

    FloatingActionButton配置
    属性 说明
    android:src 显示的图标,最好是24dp的
    app:backgroundTint 正常的背景颜色
    app:rippleColor 按下时的背景颜色
    app:elevation 正常的阴影大小(默认6dp)
    app:pressedTranslationZ 按下时的阴影大小(默认12dp)
    app:borderWidth 边框宽度
    app:layout_anchor 设置FAB的锚点,即以哪个控件为参照设置位置
    app:layout_anchorGravity FAB相对于锚点的位置
    app:fabSize normal或mini(对应56dp和40dp)

    布局:

    <com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/floatingActionButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right|bottom"
                android:layout_margin="20dp"
                app:rippleColor="#ffe5e5e5"
                app:backgroundTint="@color/black"
                app:elevation="6dp"
                app:pressedTranslationZ="6dp"
                app:fabSize="mini"
                app:borderWidth="0dp"
                android:src="@drawable/ic_dragon_avatar_9"/>
    

    效果如下


    微信图片_20201216120006.jpg
    与SnackBar的联动效果:

    FloatingActionButton天然支持与SnackBar的联动,我们只需要将FloatingActionButton设置为CoordinatorLayout的子View,在展示SnackBar时,SnackBar#make方法的View参数传入CoordinatorLayout的对象即可

    Snackbar.make(coordinatorLayout,"这是massage", Snackbar.LENGTH_LONG).setAction("这是action", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this,"你点击了action",Toast.LENGTH_SHORT).show();
         }
     }).show();
    

    效果图:

    SnackBar_FloatingActionButton[00_00_02--00_00_22].gif

    通过继承FloatingActionButton#Behavior还可以实现其他各种各样的联动效果

    继承自ViewOffsetBehavior

    这一部分Behavior是我们在日常开发中使用频次最高的
    其中两个最重要的Behavior:

    • ViewOffsetBehavior
    • AppBarLayout#Behavior
      我们在上篇博客中分享的几种效果都是通过这两种Behavior实现的

    当我们需要实现滚动控件和AppBarLayout的折叠、悬浮等效果时,滚动控件必须制定Behavior为ViewOffsetBehavior或其子类,否则是不会有协同滑动的效果的

    AppBarLayout#Behavior是AppBarLayout中各种炫酷效果的基石,AppBarLayout#Behavior负责收取和处理从CoordinatorLayout传来的滑动或者嵌套滑动事件,并根据这些事件对AppBarLayout的子控件和其自身进行变换

    有同学会说我们在xml中定义AppBarLayout时并没有指定Behavior啊,是的,如果我们没有手动指定,系统会默认指定AppBarLayout的Behavior为AppBarLayout#Behavior,这是通过AppBarLayout的类注解实现的:

    @CoordinatorLayout.DefaultBehavior(AppBarLayout.Behavior.class)
    public class AppBarLayout extends LinearLayout {
    
        static final int PENDING_ACTION_NONE = 0x0;
        static final int PENDING_ACTION_EXPANDED = 0x1;
        static final int PENDING_ACTION_COLLAPSED = 0x2;
        static final int PENDING_ACTION_ANIMATE_ENABLED = 0x4;
        static final int PENDING_ACTION_FORCE = 0x8;
          ...
    

    这两种Behavior的代码较为复杂且江湖地位显赫,本篇不作过多介绍,在接下来我们分析CoordinatorLayout源码时会着重讲解

    BottomSheetBehavior

    BottonSheetBehavior用来实现从底部滑出的抽屉效果,我们经常可以在音乐播放APP和地图APP中见到这种效果
    BottomSheetBehavior支持的属性:

    属性 含义
    behavior_peekHeight 当控件隐藏时折叠的高度
    behavior_hideable 是否可以隐藏
    app:behavior_skipCollapsed 是否跳过折叠状态

    使用方式;
    xml的定义:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <LinearLayout
                android:id="@+id/bottomSheetLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
                app:behavior_peekHeight="50dp"
                app:behavior_hideable="true">
                <androidx.constraintlayout.utils.widget.ImageFilterView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:scaleType="fitXY"
                    android:src="@drawable/yellow_zero_two"/>
    
            </LinearLayout>
        </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
        <Button
            android:id="@+id/clickBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击"/>
    </RelativeLayout>
    

    Activity:

    public class BottomSheetBehaviorActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_bottom_sheet_behavior);
            findViewById(R.id.clickBtn).setOnClickListener(v -> {
                LinearLayout bottomSheetLayout = findViewById(R.id.bottomSheetLayout);
                BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetLayout);
                bottomSheetBehavior.setState(bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED ? BottomSheetBehavior.STATE_EXPANDED : BottomSheetBehavior.STATE_COLLAPSED);
            });
    
            findViewById(R.id.floatingActionButton).setOnClickListener(v -> {
                LinearLayout bottomSheetLayout = findViewById(R.id.bottomSheetLayout);
                BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetLayout);
                bottomSheetBehavior.setState(bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED ? BottomSheetBehavior.STATE_EXPANDED : BottomSheetBehavior.STATE_COLLAPSED);
            });
        }
    }
    

    效果图:


    BottomSheetBehavior[00_00_04--00_00_24].gif

    相关文章

      网友评论

        本文标题:[Android]CoordinatorLayout简介(二)几

        本文链接:https://www.haomeiwen.com/subject/adtwgktx.html