首页 > 其他分享 >Android 嵌套布局简析

Android 嵌套布局简析

时间:2022-11-04 21:00:52浏览次数:75  
标签:14 22 int 嵌套 简析 Android public 27721 View


前言

嵌套布局是事件分发的衍生内容,理解了嵌套布局的实现方式,Md的很多效果都是毛毛雨了

​​原文地址进入​​

Android 嵌套布局简析_android

Uml 时序图形

Android 嵌套布局简析_嵌套_02

 嵌套布局实现方式,以及 5.0 中与嵌套布局有关联的组件

提起嵌套布局,MD中的 CoordinatorLayout,SwipeRefreshLayout,RecyclerView 当然还有V4包下的NestedScrollView,都有直接关系,因为他们是 NestedScrollingParent(NP) 或者 NestedScrollingChild(NC) 直接或者间接子类。

那么如何才能进行嵌套布局自定义?
通过成为NP,NC子类进行嵌套布局开发妥妥的。
下面是NP,NC 具体方法,调用时序查看blog头部的时序图结合源码进行理解
NestedScrollingChildHelper // Child辅助类
NestedScrollingParentHelper // Parent辅助类

核心类 NestedScrollingParent

package android.support.v4.view;

import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;

public interface NestedScrollingParent {

public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes);

public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes);


public void onStopNestedScroll(View target);


public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
int dxUnconsumed, int dyUnconsumed);

public void onNestedPreScroll(View target, int dx, int dy, int[] consumed);


public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed);


public boolean onNestedPreFling(View target, float velocityX, float velocityY);


public int getNestedScrollAxes();
}

核心类 NestedScrollingChild

package android.support.v4.view;

import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewParent;


public interface NestedScrollingChild {

public void setNestedScrollingEnabled(boolean enabled);


public boolean isNestedScrollingEnabled();


public boolean startNestedScroll(int axes);


public void stopNestedScroll();


public boolean hasNestedScrollingParent();


public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow);


public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow);


public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed);


public boolean dispatchNestedPreFling(float velocityX, float velocityY);
}

简单一下回调方法的介含义,以及需要在那里处理事件:

onStartNestedScroll该方法,一定要按照自己的需求返回true,该方法决定了当前控件是否能接收到其内部View(非并非是直接子View)滑动时的参数;假设你只涉及到纵向滑动,这里可以根据nestedScrollAxes这个参数,进行纵向判断。

onNestedPreScroll该方法的会传入内部View移动的dx,dy,如果你需要消耗一定的dx,dy,就通过最后一个参数consumed进行指定,例如我要消耗一半的dy,就可以写consumed[1]=dy/2

onNestedFling你可以捕获对内部View的fling事件,如果return true则表示拦截掉内部View的事件。

主要关注的就是这三个方法~

这里内部View表示不一定非要是直接子View,只要是内部View即可。

下面看一下我们具体的实现:

public class StickyNavLayout extends LinearLayout implements NestedScrollingParent
{
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes)
{
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
}
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed)
{
boolean hiddenTop = dy > 0 && getScrollY() < mTopViewHeight;
boolean showTop = dy < 0 && getScrollY() > 0 && !ViewCompat.canScrollVertically(target, -1);

if (hiddenTop || showTop)
{
scrollBy(0, dy);
consumed[1] = dy;
}
}
@Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY)
{
if (getScrollY() >= mTopViewHeight) return false;
fling((int) velocityY);
return true;
}
}

onStartNestedScroll中,我们判断了如果是纵向返回true,这个一般是需要内部的View去传入的,你要是不确定,或者担心内部View编写的不规范,你可以直接return true;

onNestedPreScroll中,我们判断,如果是上滑且顶部控件未完全隐藏,则消耗掉dy,即consumed[1]=dy;如果是下滑且内部View已经无法继续下拉,则消耗掉dy,即consumed[1]=dy,消耗掉的意思,就是自己去执行scrollBy,实际上就是我们的StickNavLayout滑动。

此外,这里还处理了fling,通过onNestedPreFling方法,这个可以根据自己需求定了,当顶部控件显示时,fling可以让顶部控件隐藏或者显示。

Eg:当然有人会说用手势 + 事件分发拦截同样可以实现这个效果,的确可以实现,只是效果会打折扣

事件分发是这样的:子View首先得到事件处理权,处理过程中,父View可以对其拦截,但是拦截了以后就无法再还给子View(本次手势内)。
NestedScrolling机制是这样的:内部View在滚动的时候,首先将dx,dy交给NestedScrollingParent,NestedScrollingParent可对其进行部分消耗,剩余的部分还给内部View。

这里针对实现了NetstedScrollingParent 的类继续log输出,直观显示滚动事件调用链。

不进行滑动

vlayout E/StickyNavLayout: onStartNestedScroll
05-22 14 E/StickyNavLayout: onNestedScrollAccepted
05-22 14 E/StickyNavLayout: onStopNestedScroll

进行滑动

05-22 14:46:11.655 27721-27721/: onStartNestedScroll
05-22 14:46:11.655 27721-27721/: onNestedScrollAccepted
05-22 14:46:11.875 27721-27721/: onNestedPreScroll
05-22 14:46:11.895 27721-27721/: onNestedPreScroll
05-22 14:46:11.915 27721-27721/: onNestedPreScroll
05-22 14:46:11.925 27721-27721/: onNestedPreScroll
05-22 14:46:11.945 27721-27721/: onNestedPreScroll
05-22 14:46:11.965 27721-27721/: onNestedPreScroll
05-22 14:46:11.975 27721-27721/: onNestedPreScroll
05-22 14:46:11.995 27721-27721/: onNestedPreScroll
05-22 14:46:12.015 27721-27721/: onNestedPreScroll
05-22 14:46:12.025 27721-27721/: onNestedPreScroll
05-22 14:46:12.045 27721-27721/: onStopNestedScroll

快速滑动

05-22 14:48:18.245 27721-27721/: onStartNestedScroll
05-22 14:48:18.245 27721-27721/: onNestedScrollAccepted
05-22 14:48:18.315 27721-27721/: onNestedPreScroll
05-22 14:48:18.315 27721-27721/: onNestedScroll

05-22 14:48:18.315 27721-27721/: onNestedPreFling
05-22 14:48:18.315 27721-27721/: onNestedFling
05-22 14:48:18.315 27721-27721/: onStopNestedScroll

抛,快速 滑动触发Fling

05-22 14:49:51.875 27721-27721/: onNestedPreFling
05-22 14:49:51.875 27721-27721/: onNestedFling

1.嵌套布局模式。依附于onTouchEvent() 进行处理。在down,move,up 中进行回调。Helper 类中实现

  1. 固定大小的 int [2],集合。 作为形参,进行传递,在函数中可以通过形参进行赋值

3.scroller 和 后面 api 19 新添加对于over 边界处理的 overscroller ,两者80% api重复,后者多了几个处理Over bound的 api

总结:

嵌套布局滑动和事件分发之间的区别,进行自定义扩展嵌套布局需要实现那些方法,实现那几个类。嵌套布局的延伸兼容性等有个大体的了解。细节部分还请自行体验


引用:
Android NestedScrolling 实战
​​​https://race604.com/android-nested-scrolling/​​​
关于View的ScrollTo, getScrollX 和 getScrollY
​​​http://www.xuebuyuan.com/2013505.html​


标签:14,22,int,嵌套,简析,Android,public,27721,View
From: https://blog.51cto.com/u_15861646/5824767

相关文章

  • Android 8.0 + Service开启方式兼容处理
    Android8.0+,对后台服务进行了限制了。如果依然采用之前startService()方式。会导致问题。前后台服务的一些区别:类别区别应用前台服务会在通知一栏显示ONGOING的Notifi......
  • 从android 谈重构
    什麽是重构可以运作的程式跟可以维护的程式之间,还有一道难以言说的鸿沟。一个程式设计之初,是用来解决特定问题。就像在前面章节的学习中,我们也已......
  • Android的BLE广播数据包解析---Android系列, 蓝牙技术(含BLE)
      一、引言理解和分析这个数据包结构(这里面也涉及广播间隔时间的设置,设备广播数据间隔设置长了,会影响设备被发现的效率;设置短时,又响应功耗)。我们所说的BLE设备,其实......
  • Android TextView 设置内容可滚动
    前言开发中scrollBar用的最多的地方就是在内容超过显示区域后,可以手动上下左右滑动来查看解决方案比较多。方案一使用一个可滑动的组件ScroolView包裹用于在内容超过显示......
  • Android Compose 修饰符类行为整理
    前言compose修饰符用来对界面组件装饰,类似ViewTree系统的组件属性,compose对于修饰符用法做了限制,RowScope,ColumScope,BoxScope,等等限制为仅可以在这些组件使用的修饰符......
  • Android LayoutParam,MarginLayoutParams
    前言开发中经常会遇到一个场景,给View动态设置margin边距,针对容器类布局比较直观。对非容器类进行margin边距设置需按不同的LayoutParams设置,否则很容造成异常。问题:为......
  • Android 使用 unity 导出obb包
    1.通过unity导出包含obb的工程。2.按照google官方给定的obb命名方式,已经存放路径进行操作​​Obb命名方式​​命名方式:[main|patch]。<扩展版本>。<程序包名称>.obbeg......
  • Android LocalBroadcastManager 使用
    前言LocalBroadcastManager简单使用。1.注册【添加IntentFilter】2.反注册3.发广播publicclassMain2ActivityextendsAppCompatActivity{@Overrideprotect......
  • Android 英文数字混排导致提前换行完美解决
    前言数字加英文混排造成,段落提前换行异常。网上可找到处理方式较多。处理方式:1.自定义TextView,测量文字宽度与父窗体宽度自行进行人为换行占主流。2.全角半角进行统一,将字......
  • android studio 4.1变更
    前言这两天被androidstudio4.1升级后遇到的问题折腾的头大。虽然自己遇到的问题和网友遇到的问题不一样。总结一句话。升级需谨慎问题归问题,这次更新还是有很多亮点。官......