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;
            }
        });

 

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM