Android 自定义Behavior

Android CoordinatorLayout之自定义Behavior 1.CoordinatorLayout是什么? CoordinatorLayout继承自ViewGroup,并实现了NestedScrollingParent2接口,类似一个功能强大的FrameLayout; CoordinatorLayout的产生主要有两个主要的目的: 1)在布局文件中作为最顶层的布局容器控件; 2)在CoordinatorLayout中直接为子控件提供特定的交互功能;相当于是给CoordinatorLayout里直接子控件建立依赖关系,使原本相互独立的控件,产生依赖关系,可以实 阅读详情

一、Behavior的介绍

1、什么是Behavior

上篇文章我们讲到CoordinatorLayout 配合AppBarLayout、CollapsingToolbarLayout实现了Toolbar的隐藏和折叠,但他们之间能够进行交互,其实就是通过一个介质CoordinatorLayout.Behavior 实现的。Behavior是CoordinatorLayout用来和各个子View通信用的代理类,用来协调CoordinatorLayout的Child Views之间的交互行为,但使用的前提是Behavior只有是CoordinatorLayout的直接子View才有意义。

2、引用Behavior的两种方式

  • app:layout_behavior布局属性
    在布局中设置,值为自定义Behavior类的名字字符串(包含路径)
  • @CoordinatorLayout.DefaultBehavior类注解
    在需要使用Behavior的控件源码定义中添加该注解,然后通过反射机制获取

二、Behavior 的两种机制

1、Dependent 机制

1.1 Dependent 介绍

这种机制主要是用来描述 两个Child View 之间的绑定依赖关系,设置Behavior 属性的Child View 跟随依赖对象Dependency View 的大小位置改变而发生改变,因此它用于一个View 监听另一个View 的状态变化。我们需要通过两个方法,来实现绑定:

    /**
     * 确定要依赖的对象
     */
     @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return super.layoutDependsOn(parent, child, dependency);
    }

    /**
     * 当依赖的对象发生变化时会自动回调这个方法
     */
    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        return super.onDependentViewChanged(parent, child, dependency);
    }
1.2、举例说明 Dependent 机制


可以看到,我对红色方块 进行拖动的时候,绿色的方块也发生了位置变化。
先自定义一个DependentBehavior,代码如下:

public class DependentBehavior extends CoordinatorLayout.Behavior<View> {
    /**
     * 构造方法
     *
     * @param context
     * @param attrs
     */
    public DependentBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 确定要依赖的对象
     *
     * @param parent
     * @param child
     * @param dependency
     * @return
     */
    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency.getId() == R.id.btn_first;
    }

    /**
     * 当依赖的对象发生变化时会自动回调这个方法
     *
     * @param parent
     * @param child
     * @param dependency
     * @return
     */
    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        // 根据要依赖的x坐标,更改当前控件的X坐标
        child.setX(parent.getWidth() - dependency.getX() - dependency.getWidth());
        child.setY(dependency.getY());
        return super.onDependentViewChanged(parent, child, dependency);
    }
}

activity_dependent.xml 代码:

<?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"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_first"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="100dp"
        android:background="@android:color/holo_red_light" />

    <Button
        android:id="@+id/btn_two"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="right"
        android:layout_marginRight="20dp"
        android:layout_marginTop="100dp"
        android:background="@android:color/holo_green_light"
        app:layout_behavior=".DependentBehavior" />
</android.support.design.widget.CoordinatorLayout>

主界面代码:

public class DependentActivity extends AppCompatActivity implements View.OnTouchListener {

    private Button mbtnFirst;
    private int lastX, lastY;    //保存手指点下的点的坐标
    private int mWidth, mHeight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dependent);
        mbtnFirst = (Button) findViewById(R.id.btn_first);
        //设置屏幕触摸事件
        mbtnFirst.setOnTouchListener(this);
    }

    /**
     * 当activity 的焦点发生改变时(View 已经绘制完成,可以获得宽高)
     *
     * @param hasFocus
     */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        mWidth = mbtnFirst.getWidth();
        mHeight = mbtnFirst.getHeight();
    }

    /**
     * 触屏事件处理
     *
     * @param view
     * @param event
     * @return
     */
    @Override
    public boolean onTouch(View view, MotionEvent event) {
        // 处理多点触摸的ACTION_POINTER_DOWN和ACTION_POINTER_UP事件
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                //将点下的点的坐标保存
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                break;

            case MotionEvent.ACTION_MOVE:
                //计算出需要移动的距离
                int dx = (int) event.getRawX() - lastX;
                int dy = (int) event.getRawY() - lastY;
                //将移动距离加上,现在本身距离边框的位置
                int left = view.getLeft() + dx;
                int top = view.getTop() + dy;
                //获取到layoutParams然后改变属性,在设置回去
                CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) view
                        .getLayoutParams();
                layoutParams.height = mHeight;
                layoutParams.width = mWidth;
                layoutParams.leftMargin = left;
                layoutParams.topMargin = top;
                view.setLayoutParams(layoutParams);

                //记录最后一次移动的位置
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                break;
        }
        return true;
    }
}

2、Nested机制

2.1 Nested 介绍

Nested机制要求CoordinatorLayout包含了一个实现了NestedScrollingChild接口的滚动视图控件,比如v7包中的RecyclerView,设置Behavior属性的Child View会随着这个控件的滚动而发生变化,涉及到的方法有:

onStartNestedScroll(View child, View target, int nestedScrollAxes)
onNestedPreScroll(View target, int dx, int dy, int[] consumed)
onNestedPreFling(View target, float velocityX, float velocityY)
onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)
onNestedFling(View target, float velocityX, float velocityY, boolean consumed)
onStopNestedScroll(View target)

下面我将简单描述下四个方法:

    /**
     *  会遍历每一个 子View,询问它们是否对滚动列表的滚动事件感兴趣,若 Behavior.onStartNestedScroll 方法返回 true,
     *  则表示感兴趣,那么滚动列表后续的滚动事件都会分发到该 子View的Behavior
     */
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int axes, int type) {
        return true;
    }

    /**
     *  处理 子View 的滚动事件
     */
    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed, int type) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
    }

    /**
     * 检测滚动距离的最终消费情况,可以继续处理 滚动事件
     */
    @Override
    public void onNestedScroll( CoordinatorLayout coordinatorLayout,  View child,  View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
    }

    /**
     * 检测到滚动事件的结束
     */
    @Override
    public void onStopNestedScroll( CoordinatorLayout coordinatorLayout,  View child,  View target, int type) {
        super.onStopNestedScroll(coordinatorLayout, child, target, type);
    }
2.2、举例说明 Nested 机制


可以看到,当下拉列表时,红色布局就会消失,向上滑动时,红色布局就会出现。
先创建一个NestedBehavior,代码如下:

public class NestedBehavior extends CoordinatorLayout.Behavior<View> {

    int offsetTotal = 0;

    public NestedBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     *  会遍历每一个 子View,询问它们是否对滚动列表的滚动事件感兴趣,若 Behavior.onStartNestedScroll 方法返回 true,
     *  则表示感兴趣,那么滚动列表后续的滚动事件都会分发到该 子View的Behavior
     */
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int axes, int type) {
        return true;
    }

    /**
     *  处理 子View 的滚动事件
     */
    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed, int type) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
        offset(child, dy);
    }

    public void offset(View child, int dy) {
        // 上次保存的位置
        int old = offsetTotal;
        // 当前的位置
        int curr = offsetTotal - dy;
        // 保证子控件的位置一直在 0-控件高度之间
        curr = Math.max(curr, -child.getHeight());
        curr = Math.min(curr, 0);
        offsetTotal = curr;
        if (old == offsetTotal) {
            return;
        }
        // 原来的位置 - 当前的位置 = 要移动的位置
        int delta = old - offsetTotal;
        child.offsetTopAndBottom(delta);
    }

}

activity_nested.xml 代码:

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_gravity="bottom"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        app:layout_behavior=".NestedBehavior">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="自定义Behavior"
            android:textColor="@android:color/white"
            android:textSize="20sp" />
    </LinearLayout>
</android.support.design.widget.CoordinatorLayout>

结尾:以上就是对自定义Behavior 的简单的介绍

最后附上源码的地址:https://github.com/smile-sxl/CoordinatorLayout

Android CoordinatorLayout进阶教程-自定义Behavior实例-标题抽屉效果-标题透明度渐变效果 Behavior名为行为控制,当我们需要在CoordinatorLayout中我们要实现与子视图中复杂的手势交互时,这个时候我们可能需要自定义Behavior行为控制,在自定义的Behavior我们可以通过对应的回调去处理相应的业务逻辑。 阅读详情

相关推荐

Android MaterialDesign系列之CoordinatorLayout&自定义Behavior

简介          MD中很重要的一个布局就是CoordinatorLayout而该布局有一个不得不提的核心中间层成员就是Behavior和NestScrolling,像我们开发中常用的FloatingActionBar与SnackBar之间的显示关系,AppBarLayout和RecyclerView或者说NestedSCrollView实现的滑动叠层效果都或多或少的涉及到核心的Behav...

crazyZhangxl的博客 501

CoordinatorLayout 和layout_behavior属性的问题

首先 layout_behavior 必须在 CoordinatorLayout直接子控件才有效果。 layout_behavior 属性指定了一个布局行为。 可以为任何View添加一个Behavior。 Behavior是一系列回调。让你有机会以非侵入的为View添加动态的依赖布局,和处理父布局(CoordinatorLayout)滑动手势的机会。app:layout_scrollFlags

修一技之长 9208

一起动才够嗨!Android CoordinatorLayout 自定义 Behavior

CoordinatorLayout 的今生前世 联动效果 现代化的 Android 开发一定对 CoordinatorLayout 不陌生,CoordinatorLayout + AppBarLayout + CollapsingToolbarLayout + Toolbar 的全家桶更是信手拈来,无需一行代码光靠 xml 就能实现下面这种折叠导航栏的炫酷效果: 这种搭配的教程已经非常多了,不...

鸿蒙开发知识记录 1009

android安卓定义,安卓自定义Behavior

自定义Behavior,最外层布局必须是CoordinatorLayout实现的效果,上滑隐藏TextView,下滑显示TextView效果如下:GIF.gifpublic class BottomShowBehavior extends CoordinatorLayout.Behavior{public BottomShowBehavior(Context context, AttributeS...

weixin_36031812的博客 250

Android自定义Behavior

BottomSheetBehavior、SwipeDismissBehavior、自定义Behavior等。原理和教程请移步严振杰的博客:http://blog.youkuaiyun.com/yanzhenjie1003。

Ubuntu20.04下运行VINS系列:VINS-Mono、VINS-Fusion和GVINS

安装好了VINS-Mono所需的ROS noetic、Eigen3.4.0、Ceres2.10和OpenCV4.2.0等。VINS-Mono是在ROS melodic以及Ceres1的环境下开发的,因此需要适配高版本的环境。

zardforever123的博客 2万+

android behavior 自定义,Android CoordinatorLayout高级用法之自定义Behavior

上次简单的说了一下CoordinatorLayout的基本用法(android特性之CoordinatorLayout用法探析实例)。其中CoordinatorLayout给我们提供了一种新的事件的处理方式,Behavior。还记得那一串字符串吗?app:layout_behavior="@string/appbar_scrolling_view_behavior"其实它并不是一个字符串资源,而它...

weixin_35734296的博客 533

Solidworks曲面建模学习(二)——3D草图

本文主要是演示有一些零件在solidworks中通过3D草来绘制会更加方便。

东东不熬夜的博客 9497

android behavior 自定义,自定义Behavior

1、这是效果 二、使用注意1、某个view需要监听另一个View的状态(位置、大小、显示状态等)(需要重写layoutDependsOn( 用来决定需要监听那些控件或者容器的状态),onDependentViewChanged(当被监听的view发生改变的时候回调))2、某个view需要监听CoordinatorLayout里边所有空间的滑动状态。(需要重写的方法:onStartNestedSc...

weixin_30849865的博客 426

Xilinx XDMA IP核配置实战:AXI Memory Mapped vs Stream选型指南(附PCIe调试技巧)

本文深入解析Xilinx XDMA IP核配置中AXI Memory Mapped与AXI Stream两种DMA接口的核心区别与选型策略。针对PCIe高速数据传输场景,详细对比了二者在数据特性、延迟、硬件资源及软件复杂度上的差异,为FPGA工程师在数据采集、实时处理等项目中做出高效设计决策提供实战指南,并附有关键的PCIe调试技巧。

qsc901234的博客 585

verilog学习——Verilog的行为建模/Behavioral modeling(2)

函数的用途是返回要在表达式中使用的值。函数定义始终以关键字function开始,后跟返回类型、名称和在参数中的端口列表。函数以关键字endfunction结束。函数至少有一个输入,如果不返回任何内容,则返回类型为void。由两种方法可以声明函数的输入;函数定义隐式地创建一个与函数同名的内部变量。通过将函数结果分配给内部变量来初始化返回值。函数调用是带有表达式的操作数。① 函数不能包含任何时间控制语句,如#、@、wait、posedge、negedge;

LXY241638的博客 1357

android behavior 自定义,自定义Behavior(一)

跟谁手指移动的一个View布局文件:xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent">android:layout_width="wrap_content"android:layout_height...

weixin_31318441的博客 271

【博弈论】势博弈(potential game)、EPG以及最佳响应、Nash均衡和帕累托(pareto)最优的理解

文章目录前言一、Potential game二、Nash均衡和Pareto-optimal(帕累托最优)1.Nash 均衡2.Pareto最优三、Best response(最佳响应)四、Exact potential game(EPG)1.合作-傀儡博弈2.合作博弈3.傀儡博弈4.自激博弈5.双边对称交互博弈使用理解 前言 本文主要详细讲解potential game的概念以及Exact potential game 的定义和分类,以及这么博弈方法是如何在论文中引入并使用的,本文仅是对自己在该模块

weixin_44535200的博客 2万+

android 史上最简单behavior,Android CoordinatorLayout高级用法之自定义Behavior

Android CoordinatorLayout高级用法之自定义Behavior发布时间:2020-10-22 02:04:52来源:脚本之家阅读:114作者:FightSeeker上次简单的说了一下CoordinatorLayout的基本用法(android特性之CoordinatorLayout用法探析实例)。其中CoordinatorLayout给我们提供了一种新的事件的处理方式,Beha...

weixin_39984403的博客 431

cadence CIS 库建立--建立自己维护的CIS数据库

遇到一个问题,在使用cadecnce的时候,就是没有自己的本地/分享的数据库。 在画原理图或者PCB的时候,如果能搭建一个自己的数据库,在局域网或者本地 就好了。出于这样的想法,做了一些探索,找到了一种可能的答案。 由于数据库编制知识的缺乏,要自己建一个数据库似乎花费的时间会比较多。 偶发奇想,如果能够改编CIS 自带的数据库 另建立副本进行维护 就能够省下不少麻烦。 先说下CIS 是个啥。网上一搜:总之CIS 是个好东西。 功能强大。 点击CIS capture 中的 Options CIS Config

qq_29776365的博客 2万+

嵌入式工程师成长之路(10)——项目举例

送给大学毕业后找不到奋斗方向的你(每周不定时更新)

云轩阁 5万+

android behavior 自定义,Android应用开发之Android CoordinatorLayout高级用法之自定义Behavior...

本文将带你了解Android应用开发Android CoordinatorLayout高级用法之自定义Behavior,希望本文对大家学Android有所帮助。上次简单的说了一下CoordinatorLayout的基本用法(android特性之CoordinatorLayout用法探析实例)。其中CoordinatorLayout给我们提供了一种新的事件的处理方式,Behavior。还记得那一串字...

weixin_39761481的博客 161

基于STM32、HAL库的GZP6816D气压传感器 驱动程序设计

测量范围:0-16kPa(可根据型号不同有变化)工作电压:1.8V-3.6V。高精度:±1% FS。

corlin6688的博客 217

Android开发笔记(一百三十七)自定义行为Behavior

协调布局CoordinatorLayout能够让内部的子控件互相配合着移动,这跟以往孤立的控件运动截然不同,协调运动的结果,意味着App画面更加流畅、自然,也更符合日常生活中的动作场景。如果你对CoordinatorLayout的用法还不太了解的话,建议先浏览这篇博文熟悉一下《Android开发笔记(一百三十四)协调布局CoordinatorLayout》。一般我们使用CoordinatorLay

aqi00的博客 4296

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android 自定义behavior 实现上滑 隐藏底部view

布局 &lt;android.support.design.widget.CoordinatorLayout  android:layout_width="match_parent"  android:layout_height="match_parent"&gt;    &lt;include layout="@layout/toolbar"/&gt;    &lt;include...

pengpenggege_lp的博客 1560

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android Design 自定义Behavior

自从Android推出Design后,就广受各位开发者的喜爱,因为以前很多高级特效都需要我们自己去写,而现在Design库内置类很多实用的控件,很多复杂的需求用设个库就能满足,记得以前写自定义控件就经常遇到触摸事件方面的问题,比如外层ViewGroup将事件拦截后,在通过某些特定操作后,将事件还给内部子View处理,这种事件处理就很麻烦,因为在一次事件中外部ViewGroup一旦拦截了事件,子类就...

peakchao 557

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Android 利用CoordinatorLayout vs Behavior机制自定义滑动删除布局

Android 利用CoordinatorLayout vs Behavior机制自定义滑动删除布局: 0.先给个图片样式。 1.滑动删除的实现有很多种,本文介绍自己初步实现的一个拖拽滑动的自定义布局。供参考。 2.原理:SlidingView继承CoordinatorLayout重写dispatchTouchEvent()方法在合适的时候对子view事件进行拦截。 3.S

qq_33214392的博客 1032

Android开发之自定义Behavior

连续讲了几章关于CoordinationLayout的用法,以及Google给我们提供了两个非常强大的Behavior,以及我们自己实现了一个较为简单的Behavior,今天我带领大家通过实现两个简单的效果来讲解一下Behavior,以及实现我们自定义Behavior的效果。

等待着冬天的风的博客 986
上一篇: Android CoordinatorLayout的使用——实现Toolbar的隐藏和折叠
下一篇: Android View 的滑动
谦行
博客等级 码龄11年 182粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值