zoukankan      html  css  js  c++  java
  • FloatingActionButton的一点学习感悟

      最近在学习android材料设计的新控件,前面一篇文章讲到 CoordinatorLayout 结合几个新控件可以实现的几个效果。其中第一个是,Coordinatorlayout + FloatingActionButton,配合使用,当弹出 Snackbar 的时候,FloatingActionBar会跟随上移和下移。这次再针对 FloatingActionButton 具体分析一下。先贴出布局文件和java代码:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <Button
            android:id="@+id/btnSnackBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击弹出SnackBar"/>
    
    
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/floatingActionBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|right"
            android:src="@mipmap/ic_launcher" />
        
    </android.support.design.widget.CoordinatorLayout>
    public class MainActivity extends Activity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_sixth);
            ((Button) findViewById(R.id.btnSnackBar)).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Snackbar.make(v,"这是一个snackBar",Snackbar.LENGTH_SHORT).show();
                }
            });
        }
    }

     代码很简洁,效果如下:

      

      这个效果只有在CoordinatorLayout下,FloatingActionButton 配合 Snackbar 使用才会有。

      我们知道,FloatingActionButton 间接继承自 ImagButton, 如果将 FloatingActionButton 换成常用的 ImagButton 或者 ImageView,效果将不存在。为什么会这样呢。在 FloatingActionButton 的定义中发现,通过反射,利用注解注入了一个 behavior 属性。FloatingActionButton 类中定义了一个内部类——Behaivor,继承自 CoordinatorLayout.Behavior<FloatingActionButton> 。里面有两个方法如下:

      

         @Override
         public boolean layoutDependsOn(CoordinatorLayout parent,FloatingActionButton child, View dependency) {
                // We're dependent on all SnackbarLayouts (if enabled)
                return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout;
            }
    
         @Override
            public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child,View dependency) {
                if (dependency instanceof Snackbar.SnackbarLayout) {
                    updateFabTranslationForSnackbar(parent, child, dependency);
                } else if (dependency instanceof AppBarLayout) {
                    // If we're depending on an AppBarLayout we will show/hide it automatically
                    // if the FAB is anchored to the AppBarLayout
                    updateFabVisibility(parent, (AppBarLayout) dependency, child);
                }
                return false;
            }
    
    
         private float getFabTranslationYForSnackbar(CoordinatorLayout parent,FloatingActionButton fab) {
                float minOffset = 0;
                final List<View> dependencies = parent.getDependencies(fab);
                for (int i = 0, z = dependencies.size(); i < z; i++) {
                  final View view = dependencies.get(i);
                  if (view instanceof Snackbar.SnackbarLayout && parent.doViewsOverlap(fab, view)) {
                        minOffset = Math.min(minOffset,ViewCompat.getTranslationY(view) - view.getHeight());
                   }
                }
                return minOffset;
              }

        layoutDependsOn 方法,判断底下弹出的是不是snackbar,如果是,floatingactionbutton才会联动。

        当需要联动的snackbar向上移动的过程中,会不断调用 onDependentViewChanged 方法。

         getFabTranslationYForSnackbar 用来获取SnackBar逐渐弹出来的时候变化的高度。

        明白了这三个方法之后,我们就可以对这个效果进行修改写。下面我们自己写一个类,让其继承自 CoordinatorLayout.Behavior<FloatingActionButton>,

     让FloatingActionButton在上升过程中实现随高度变化旋转效果。

        代码如下:

        

    public class MyBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
        /**
         * Default constructor for instantiating Behaviors.
         */
        public MyBehavior() {
        }
    
        /**
         * Default constructor for inflating Behaviors from layout. The Behavior will have
         * the opportunity to parse specially defined layout parameters. These parameters will
         * appear on the child view tag.
         *
         * @param context
         * @param attrs
         */
        public MyBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        /**
         * 判断底下弹出的是不是snackbar,如果是,floatingactionbutton才会联动
         *
         * @param parent
         * @param child
         * @param dependency
         * @return
         */
        @Override
        public boolean layoutDependsOn(CoordinatorLayout parent,
                                       FloatingActionButton child, View dependency) {
    
            return dependency instanceof Snackbar.SnackbarLayout;
        }
    
    
        /**
         * 当需要联动的snackbar向上移动的过程中,会不断调用这个方法
         *
         * @param parent
         * @param child
         * @param dependency
         * @return
         */
        @Override
        public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child,
                                              View dependency) {
    
            float fTransY = getFabTranslationYForSnackbar(parent, child);
    
            float iRate = -fTransY / dependency.getHeight();
    
            child.setRotation(iRate * 90);
    
            child.setTranslationY(fTransY);
    
            return false;
        }
    
    
        /**
         * 用来获取SnackBar逐渐弹出来的时候变化的高度
         *
         * @param parent
         * @param fab
         * @return
         */
        private float getFabTranslationYForSnackbar(CoordinatorLayout parent,
                                                    FloatingActionButton fab) {
            float minOffset = 0;
            final List<View> dependencies = parent.getDependencies(fab);
            for (int i = 0, z = dependencies.size(); i < z; i++) {
                final View view = dependencies.get(i);
                if (view instanceof Snackbar.SnackbarLayout && parent.doViewsOverlap(fab, view)) {
                    minOffset = Math.min(minOffset,
                            ViewCompat.getTranslationY(view) - view.getHeight());
                }
            }
            return minOffset;
        }
    }

       然后修改布局文件,为 FloatingActionButton 设置 layout_behavior 属性为自定义的MyBehavior,

       

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout 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">
    
        <Button
            android:id="@+id/btnSnackBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击弹出SnackBar"/>
    
    
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/floatingActionBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|right"
            app:layout_behavior="com.example.joy.coordinatorlayouttest.MyBehavior"
            android:src="@mipmap/ic_launcher" />
    
    </android.support.design.widget.CoordinatorLayout>

      效果如下:

      

       

  • 相关阅读:
    Gym
    UVALive
    UVALive
    UVALive
    UVALive
    Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset Trie
    HDU 5816 Hearthstone 概率dp
    欧几里德与扩展欧几里德算法(转)
    差分约束系统详解(转)
    2016年第七届蓝桥杯C/C++程序设计本科B组决赛
  • 原文地址:https://www.cnblogs.com/joy99/p/5664827.html
Copyright © 2011-2022 走看看