• CoordinatorLayout的使用,以及FloatingActionButton、snakebar的简单用法


     一、CoordinatorLayout基本介绍

    CoordinatorLayout作为“super-powered FrameLayout”基本实现两个功能 (demo是实现 http://blog.csdn.net/huachao1001/article/details/51554608 中的)
    1、作为顶层布局 
    2、调度协调子布局

      通过实验发现它也可以嵌套在其他的布局文件内,但它只能协调它的子布局。且与snakebar连着使用时,来控制弹出消息的位置,这个在后面介绍snakebar时讲。

    基本用法

      1、引入相应的库

      使用CoordinatorLayout可以实现一些炫酷的动态效果,使用它首先得在app的gradle中引入相应的库:

    dependencies {    
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'
    }

    node: 按网上的大多资料是compile 'com.android.support:design:22.2.1' , 这里我们引入的上面的支持库版本一致,否则会报错。

      2、将CoordinatorLayout内部子控件或者布局设定behavior行为,该控件设定了监听其它的子控件或者布局来执行相应动作。下面给出简单的一个布局:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.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="com.example.user.coordinatorlayouttest.MainActivity">
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#FFCC00"
        android:text="Hello"
        app:layout_behavior="com.example.user.coordinatorlayouttest.MyBehavior" />
    
    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="30dp"
        android:background="#3366CC"
        android:text="dependency"
        android:id="@+id/nice_to_me_to_you"/>
    </android.support.design.widget.CoordinatorLayout>

    其中button就设定了behaviour,其实就是来监听一些控件的动作来执行相应的动作。

    3、实现behaviour:

    package com.example.user.coordinatorlayouttest;
    
    import android.content.Context;
    import android.support.design.widget.CoordinatorLayout;
    import android.util.AttributeSet;
    import android.util.DisplayMetrics;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    /**
     * Created by user on 2017/5/3.
     */
    public class MyBehavior extends CoordinatorLayout.Behavior<Button> {
        private int width;
    
        public MyBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);
            DisplayMetrics display = context.getResources().getDisplayMetrics();
            width = display.widthPixels;
        }
    
        @Override
        public boolean layoutDependsOn(CoordinatorLayout parent, Button child, View dependency) {
            //如果dependency是TextView的实例,说明它就是我们所需要的Dependency,只有返回true时候,下面的方法才会执行
            return dependency instanceof TextView;
        }
    
        //每次dependency位置发生变化,都会执行onDependentViewChanged方法
        @Override
        public boolean onDependentViewChanged(CoordinatorLayout parent, Button btn, View dependency) {
    
            //根据dependency的位置,设置Button的位置
    
            int top = dependency.getTop();
            int left = dependency.getLeft();
    
            int x = width - left - btn.getWidth();
            int y = top;
    
            setPosition(btn, x, y);
            return true;
        }
    
        private void setPosition(View v, int x, int y) {
            CoordinatorLayout.MarginLayoutParams layoutParams = (CoordinatorLayout.MarginLayoutParams) v.getLayoutParams();
            layoutParams.leftMargin = x;
            layoutParams.topMargin = y;
            v.setLayoutParams(layoutParams);
        }
    }

      这里设定了子布局中TextView的对象是dependency,当TextView的位置发生变化时,button的位置也会相应发生变化(竖直方向移动一致,横向方向是相反的)

      4、定义dependency的位移方式,(其实大多dependency是自定义的控件),这里设计点触控,总结一下:点触控时候位移量最好用getRawX函数来获取,用getX是获得控件内部坐标,而控件本身在移动,函数执行有一定频率会导致位移量有丢失且图片抖动,用下面的方式就不会了:

     textView = (TextView) findViewById(R.id.nice_to_me_to_you);
            textView.setOnTouchListener(new View.OnTouchListener() {
                int toLeft,toTop,sx ,sy;
                @Override
                public boolean onTouch(View v, MotionEvent event) {
    
                   int action = event.getAction();
                   switch (action)
                   {
                       case MotionEvent.ACTION_DOWN:
                           sx = (int) event.getRawX();
                           sy = (int) event.getRawY();
                           toLeft = textView.getLeft();
                           toTop  = textView.getTop();
                           break;
    
                       case MotionEvent.ACTION_MOVE:
                           int sx2 = (int) event.getRawX();
                           int sy2 = (int) event.getRawY();
                           CoordinatorLayout.MarginLayoutParams layoutParams = (CoordinatorLayout.MarginLayoutParams) v.getLayoutParams();
                           layoutParams.leftMargin = toLeft + sx2 - sx;
                           layoutParams.topMargin =toTop + sy2 - sy;
                           v.setLayoutParams(layoutParams);
                           break;
                   }
                    return  true;
                }
            });

    综合上面,CoordinatorLayout的用法介绍完毕了,但CoordinatorLayout通常与一些控件结合起来用,以达到一些特殊的效果,如:FloatingActionButton、snakebar、tabLayout,toolbar 、下面简单介绍FloatingActionButton、snakebar控件的基本用法:关于后面2个在后面的博客中再说。

    二、snakebar 基本用法

      snakebar也是与CoordinatorLayout一样需要引入compile 'com.android.support:design:23.3.0' ,其特点如下:(参考 http://blog.csdn.net/u013320868/article/details/51906896)

      1)SnackBars 提供了一个轻量级的反馈操作,他们在屏幕的底部显示一条简短的信息,如果是较大的设备就显示在左下角。SnackBar出现在屏幕中所有其他元素的上方,同一时间只能显示一条SnackBar。

      2)在超时或者用户在屏幕上完成了交互的时候SnackBar会自动消失,特别是在召唤了新的表层(意思是SnackBar本来是最外层的,然后在SnackBar上又新添加了一层)或者Activity的时候。SnackBar能在屏幕上侧滑。

      3)SnackBar能包含一个action使用setAction方法

      4)你可以通过它的CallBack来得知Snackbar是显示还是隐藏

    与Toast进行比较,SnackBar有优势

      1.SnackBar可以自动消失,也可以手动取消(侧滑取消,但是需要在特殊的布局中,后面会仔细说)

      2.SnackBar可以通过setAction()来与用户进行交互

      3.通过CallBack我们可以获取SnackBar的状态

    下面介绍一下

     node:snakeBar通常与CoordinatorLayout连用,出现在CoordinatorLayout布局的下发,弹出一条消息,且可以设置一个action事件,但有时候没有CoordinatorLayout或者不在CoordinatorLayout布局内。下面的结论是通过实验得到的:

       1、当布局中有CoordinatorLayout,不管引入snakeBar的控件是CoordinatorLayout 子控件还是CoordinatorLayout的子布局的子控件,它都会出现在CoordinatorLayout布局的最下面。

      2、当引入snakebar的控件不在CoordinatorLayout内部时候,(即使有CoordinatorLayout,但引入snakebar控件不在其内)则snakebar会出现在最上层的framLayout的底部,即屏幕的底部。

     下面给出个简单的例子:

    布局文件:

    <?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">
    
        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:id="@+id/f1"
            android:background="@android:color/darker_gray"
            >
            <android.support.design.widget.FloatingActionButton
                android:id="@+id/fab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="end|bottom"
                android:layout_margin="16dp"
    
                android:background="@android:color/holo_red_light" />
        </android.support.design.widget.CoordinatorLayout>
    
    </RelativeLayout>

    然后在activity的onCreate()中写入下面方法后,当点击悬浮按钮的时候就会在200dp的位置出现snakebar,上面说到的引入snakebar按钮就是fab:

     findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Snackbar snackBar =Snackbar.make(view,"it is snackbar!",Snackbar.LENGTH_SHORT);
                    //设置SnackBar背景颜色
                    snackBar.getView().setBackgroundColor(Color.RED);
                    //设置按钮文字颜色
                    snackBar.setActionTextColor(Color.WHITE);
                    //设置点击事件
                    snackBar.setAction("点击", new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(MainActivity.this,"It is Toast!",Toast.LENGTH_SHORT).show();
                        }
                    });
                    //设置回调
                    snackBar.setCallback(new Snackbar.Callback() {
    
                        @Override
                        public void onDismissed(Snackbar snackbar, int event) {
                            super.onDismissed(snackbar, event);
                            Toast.makeText(MainActivity.this, "Snackbar dismiss", Toast.LENGTH_SHORT).show();
                        }
    
    
                        @Override
                        public void onShown(Snackbar snackbar) {
                            super.onShown(snackbar);
                            Toast.makeText(MainActivity.this, "Snackbar show", Toast.LENGTH_SHORT).show();
                        }
                    }).show();
                }
            });

      可以看出,我们可以setAction来设定点击时间,而Snakebar.LEMGTH_SHORT是显示的时间,它有三种方式:  

    Snackbar.LENGTH_SHORT// 短时间显示,然后自动取消

    Snackbar.LENGTH_LONG// 长时间显示,然后自动取消

    Snackbar.LENGTH_INDEFINITE// 不消失显示,除非手动取消

      且我们可以设定回调函数,当snakeBar显示和消失时候完成一些事情

    3、FloatingActionButton

     关于floatingActionButton介绍网上很多,它继承自ImageView,关于它的介绍主要集中在于设置背景色和阴影的设置上:

     1、它也是来自上面所说的支持库,在build.grade文件中写上

    compile 'com.android.support:design:23.2.0'

     2、关于它的几个重要属性的介绍

        1、app:borderWidth=""------------------边框宽度,通常设置为0 ,用于解决Android 5.X设备上阴影无法正常显示的问题

        2、app:backgroundTint=""---------------按钮的背景颜色,不设置,默认使用theme中colorAccent的颜色 (默认颜色为主题中colorAccent的颜色,关于如何自定义主题,以后的文章再讲)

        3、app:rippleColor=""--------------------点击的边缘阴影颜色

        4、app:elevation=""----------------------边缘阴影的宽度

        5、app:pressedTranslationZ="16dp"-----点击按钮时,按钮边缘阴影的宽度,通常设置比elevation的数值大

    3 可以看出属性是app开头的,因此在布局文件前面加上:

    xmlns:app="http://schemas.android.com/apk/res-auto"

     4、通过网上的设置background然后写一个drawable文件,写一个背景的选择器,在按下时候变色,如下:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_pressed="false" android:drawable="@color/floatBack1"></item>
        <item android:state_pressed="true" android:drawable="@color/floatBackPressed"></item>
    </selector>

    发现将该drawable给background属性无效,给backgroundTint后变色了但不是我们设定的颜色,通过查看源码,发现setbackground源码如下:

     @Override
        public void setBackgroundDrawable(Drawable background) {
            Log.i(LOG_TAG, "Setting a custom background is not supported.");
        }
    
        @Override
        public void setBackgroundResource(int resid) {
            Log.i(LOG_TAG, "Setting a custom background is not supported.");
        }
    
        @Override
        public void setBackgroundColor(int color) {
            Log.i(LOG_TAG, "Setting a custom background is not supported.");
        }

    它本身没有实现这些函数,因此设置background属性是无效的,它的一些属性都是靠实现了ShadowViewDelegate接口的类完成的,而属性设置中的backgournd无效,智能通过backgroundTint来设定背景,而backgroundTint使用drawable里的文件颜色是改变了但不是我们设定的,(原因不是很清楚)因此在代码中来设定背景了:

    比如下面我们设定当点击悬浮图标时候背景色跟着变化,点击完毕时候恢复原来颜色时,主要是设置了按键的OntouchListener

     floatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
            floatingActionButton.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffff0000")));//设定默认色
            floatingActionButton.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction())
                    {
                        case MotionEvent.ACTION_MOVE:
                            floatingActionButton.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffffff00")));//手指按下时候变色
                            break;
                        case    MotionEvent.ACTION_UP:
                            floatingActionButton.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffff0000")));//手指离开时候恢复
                            break;
    
                    }
                    return true;
                }
            });

      

      

  • 相关阅读:
    关于亮剑,文化大革命的一点感想
    iOS -- block
    runtime -- 方法交换的坑自定义方法不执行
    iOS-UITableViewCell
    iOS debug模式
    iOS 将storybord中的视图与viewcontroller相关联
    gitignore的编写规则
    使用cocopods安装Alamofire后各种报错
    ReactNative--坑--'React/RCTBridgeModule.h' file not found
    12-2描点 学完路径可以对整个工具条做个概括 绘图类已完成
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/6803185.html
Copyright © 2020-2023  润新知