您的位置:首页 > 移动开发 > Android开发

Android开发 之 (协调布局)CoordinatorLayout与(依赖行为)Behavior

2017-07-27 23:46 435 查看

CoordinatorLayout与Behavior

翻译过来就是协调布局和依赖行为,这两个是内部类关系

在我这里有两种用途:看效果



第一种,两个空间的y坐标形成依赖关系,坐标依赖



第二种,滑动以来关系

上代码:
第一种:
<?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">

<com.example.zxq.bsquxian.views.ScrPositionTextView
android:layout_width="200dp"
android:layout_height="200dp"
android:gravity="center"
android:textSize="20sp"
android:textColor="#FF0"
android:background="#000"
android:text="main"/>
<Button
android:layout_width="150dp"
android:layout_height="150dp"
android:text="BUTTOn"
app:layout_behavior="com.example.zxq.bsquxian.views.MyBehavior"

ce5d
>
</Button>

</android.support.design.widget.CoordinatorLayout>
当然了这种效果是基于协调布局开发的,所以布局必须使用协调布局
代码中button添加一个属性layout_behavior就是建立以来关系的属性,MyBehavior这个类是自定义的,这里属性值:自定义的类的包名+类名。

自定义的MyBehavior类:
package com.example.zxq.bsquxian.views;

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;

/**
* Created by Administrator on 2017/7/25 0025.
*/

public class MyBehavior extends CoordinatorLayout.Behavior<Button> {
public MyBehavior(Context context, AttributeSet attrs)
{
super(context,attrs);
}

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, Button child, View dependency) {
//如果dependency 是 ScrPositionTextView, 就依赖
return dependency instanceof ScrPositionTextView;
}

//每次dependency位置发生变化,都会执行onDependentViewChanged方法
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, Button btn, View dependency) {

//根据dependency的位置,设置Button的位置
int x = 0;
int y = (int) dependency.getY();
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);
}
}
在上面的layoutDependsOn方法中判断依赖对象,要依赖到哪个组件上。这里依赖了一个自定义TextView,当然这里也可以通过id判断依赖关系

自定义的TextView:
package com.example.zxq.bsquxian.views;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;

/**
* Created by Administrator on 2017/7/25 0025.
*/

public class ScrPositionTextView extends android.support.v7.widget.AppCompatTextView {
private int startx;
private int starty;
public ScrPositionTextView(Context context) {
super(context);
}

public ScrPositionTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public ScrPositionTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
startx= (int) event.getRawX();
starty= (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int lastX= (int) event.getRawX();
int lastY= (int) event.getRawY();
int movex= lastX-startx;
int movey= lastY-starty;
startx= lastX;
starty= lastY;
CoordinatorLayout.MarginLayoutParams layoutParams= (CoordinatorLayout.MarginLayoutParams) getLayoutParams();
int left = layoutParams.leftMargin+movex;
int top = layoutParams.topMargin+movey;
layoutParams.leftMargin=left;
layoutParams.topMargin=top;
setLayoutParams(layoutParams);
requestFocus();
break;
}
return true;
}
}
这里动态改变textview的位置就ok,自己的y坐标会自动关联到那个button上去的。

第二种代码:
Behavior最大的用处在于对滑动事件的处理。就像CollapsingToolbarLayout的那个酷炫效果一样。

自定义的Behavior:这里需要重写以下几个方法

package com.example.zxq.bsquxian.views;

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
* Created by Administrator on 2017/7/27 0027.
*/

public class ScrollBehavior extends CoordinatorLayout.Behavior {
int offsetTotal = 0;
boolean scrolling = false;

public ScrollBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return true;//这里返回true,才会接受到后续滑动事件。
}

@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
//进行滑动事件处理
offset(child,dyConsumed);
}

@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) {
//当进行快速滑动
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}

@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent ev) {
return super.onInterceptTouchEvent(parent, child, ev);
}

@Override
public boolean onTouchEvent(CoordinatorLayout parent, View child, MotionEvent ev) {
return super.onTouchEvent(parent, child, ev);
}

public void offset(View child,int dy){
int old = offsetTotal;
int top = offsetTotal - dy;
top = Math.max(top, -child.getHeight());
top = Math.min(top, 0);
offsetTotal = top;
if (old == offsetTotal){
scrolling = false;
return;
}
int delta = offsetTotal-old;
child.offsetTopAndBottom(delta);
scrolling = true;
}

}


布局文件;
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<android.support.v4.widget.NestedScrollView
android:id="@+id/second"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/textView"
style="@style/TextAppearance.AppCompat.Display3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="128dp"
android:background="@android:color/holo_red_light"
android:text="A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>

<ImageView
android:id="@+id/first"
android:layout_width="match_parent"
android:layout_height="128dp"
app:layout_behavior="com.example.zxq.bsquxian.views.ScrollBehavior"
android:background="@mipmap/meinv"/>

</android.support.design.widget.CoordinatorLayout>


注意被依赖的View只有实现了NestedScrollingChild接口的才可以将事件传递给CoordinatorLayout。

但注意这个滑动事件是对于CoordinatorLayout的。所以只要CoordinatorLayout有NestedScrollingChild就会滑动,他滑动就会触发这几个回调。无论你是否依赖了那个View。
Imageview设置关联属性

有关自己的事件处理可以在这2个回调与View中的事件分发是一样的。所有Behavior能在子View之前收到CoordinatorLayout的所有触摸事件。可以进行拦截,如果拦截事件将不会流经子View。因为这2个方法都是在CoordinatorLayout的 回调中

其实之前讲的AppBarLayout效果也是这个原理:
AppBarLayout自带一个Behivior。直接在源码里注解声明的。这个Behivior也只能用于AppBarLayout。

作用是让他根据CoordinatorLayout上的滚动手势进行一些效果(比如收缩)。与ScrollingViewBehavior是无关的,加不加ScrollingViewBehavior不影响收缩。

只不过只有某些可滑动View才会把滑动事件响应给CoordinatorLayout才能继而响应给AppBarLayout。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: