NestedScrollView嵌套RecycleView 滑动 实现上滑隐藏 下滑显示头部效果
废了好大的劲才弄好的,记下来 方便以后查看
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private List<String> mDatas;
private HomeAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
//设置布局管理器
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//设置adapter
mRecyclerView.setAdapter(mAdapter = new HomeAdapter());
}
protected void initData() {
mDatas = new ArrayList<String>();
for (int i = 'A'; i < 'z'; i++) {
mDatas.add("" + (char) i);
}
}
class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> {
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
MainActivity.this).inflate(R.layout.item_home, parent,
false));
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.tv.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public MyViewHolder(View view) {
super(view);
tv = (TextView) view.findViewById(R.id.id_num);
}
}
}
然后是最关键的NestedScrollview 是为了配合嵌套滑动的, NestedScrollview最关键有两个接口的实现 一个是 NestedScrollingChild 一个是NestedScrollingParent
先是NestedScrollingParent
public class MyNestedScrollParent extends LinearLayout implements NestedScrollingParent {
private String Tag = "MyNestedScrollParent";
private View topView ;
private View centerView;
private View contentView;
private MyNestedScrollChildL nsc ;
private NestedScrollingParentHelper mParentHelper;
private int imgHeight;
private int tvHeight;
private int mLastTouchY;
public boolean topShow;
public MyNestedScrollParent(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyNestedScrollParent(Context context) {
super(context);
init();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
topView = getChildAt(0);
centerView = getChildAt(1);
contentView = getChildAt(2);
topView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if(imgHeight<=0){
imgHeight = topView.getMeasuredHeight();
Log.i(Tag,"imgHeight:"+imgHeight+",tvHeight:"+tvHeight);
}
}
});
centerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if(tvHeight<=0){
tvHeight = centerView.getMeasuredHeight();
Log.i(Tag,"imgHeight:"+imgHeight+",tvHeight:"+tvHeight);
}
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), topView.getMeasuredHeight() + centerView.getMeasuredHeight() + contentView.getMeasuredHeight());
}
public int getTopViewHeight(){
Log.i(Tag,"getTopViewHeight--"+topView.getMeasuredHeight());
return topView.getMeasuredHeight();
}
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
Log.i(Tag,"onStartNestedScroll--"+"child:"+child+",target:"+target+",nestedScrollAxes:"+nestedScrollAxes);
return true;
}
private void init() {
mParentHelper = new NestedScrollingParentHelper(this);
}
@Override
public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
Log.i(Tag,"onNestedScrollAccepted"+"child:"+child+",target:"+target+",nestedScrollAxes:"+nestedScrollAxes);
mParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes);
}
@Override
public void onStopNestedScroll(View target) {
Log.i(Tag,"onStopNestedScroll--target:"+target);
mParentHelper.onStopNestedScroll(target);
}
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
Log.i(Tag,"onNestedScroll--"+"target:"+target+",dxConsumed"+dxConsumed+",dyConsumed:"+dyConsumed
+",dxUnconsumed:"+dxUnconsumed+",dyUnconsumed:"+dyUnconsumed);
}
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
if(showImg(dy)||hideImg(dy)){//如果父亲自己要滑动,则拦截
consumed[1]=dy;
scrollBy(0,dy);
Log.i("onNestedPreScroll","Parent滑动:"+dy);
}
Log.i(Tag,"onNestedPreScroll--getScrollY():"+getScrollY()+",dx:"+dx+",dy:"+dy+",consumed:"+consumed);
}
@Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
Log.i(Tag,"onNestedFling--target:"+target);
return false;
}
@Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
Log.i(Tag,"onNestedPreFling--target:"+target);
return false;
}
@Override
public int getNestedScrollAxes() {
Log.i(Tag,"getNestedScrollAxes");
return 0;
}
@Override
public void scrollTo(int x, int y) {
if(y<0){
y=0;
}
if(y>imgHeight){
y=imgHeight;
}
super.scrollTo(x, y);
}
/**
下拉的时候是否要向下滑动显示图片
*/
public boolean showImg(int dy){
if(dy<0){
// if(getScrollY()>0&&nsc.getScrollY()==0){//如果parent外框,还可以往上滑动
if(getScrollY()>0){
return true;
}
}
return false;
}
/**
* 上拉的时候,是否要向上滑动,隐藏图片
* @return
*/
public boolean hideImg(int dy){
if(dy>0){
if(getScrollY()<imgHeight){//如果parent外框,还可以往下滑动
return true;
}
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
return true;
}
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return super.onInterceptTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i("aaa","getY():getRawY:"+event.getRawY());
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mLastTouchY = (int) (event.getRawY() + 0.5f);
break;
case MotionEvent.ACTION_MOVE:
int y = (int) (event.getRawY() + 0.5f);
int dy = mLastTouchY - y;
mLastTouchY = y;
if(showImg(dy)||hideImg(dy)){//如果父亲自己要滑动
scrollBy(0,dy);
}
break;
case MotionEvent.ACTION_UP:
break;
}
return super.dispatchTouchEvent(event);
}
}
然后是NestedScrollingChild
public class MyNestedScrollChild extends ScrollView implements NestedScrollingChild {
private String Tag = "MyNestedScrollChild";
private NestedScrollingChildHelper mScrollingChildHelper;
public MyNestedScrollChild(Context context) {
super(context);
init(context);
}
public MyNestedScrollChild(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyNestedScrollChild(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void init(Context context) {
final ViewConfiguration configuration = ViewConfiguration.get(context);
}
@Override
public void setNestedScrollingEnabled(boolean enabled) {
Log.i(Tag, "setNestedScrollingEnabled:" + enabled);
getScrollingChildHelper().setNestedScrollingEnabled(enabled);
}
@Override
public boolean isNestedScrollingEnabled() {
Log.i(Tag, "isNestedScrollingEnabled");
return getScrollingChildHelper().isNestedScrollingEnabled();
}
@Override
public boolean startNestedScroll(int axes) {
boolean bl = getScrollingChildHelper().startNestedScroll(axes);
Log.i(Tag, "startNestedScroll:axes=" + axes + ",bl:" + bl);
Log.i(Tag, "hasNestedScrollingParent=" + getScrollingChildHelper().hasNestedScrollingParent());
return bl;
}
@Override
public void stopNestedScroll() {
Log.i(Tag, "stopNestedScroll");
getScrollingChildHelper().stopNestedScroll();
}
@Override
public boolean hasNestedScrollingParent() {
Log.i(Tag, "hasNestedScrollingParent");
return getScrollingChildHelper().hasNestedScrollingParent();
}
@Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
int dyUnconsumed, int[] offsetInWindow) {
Log.i(Tag, "dispatchNestedScroll:dxConsumed:" + dxConsumed + "," +
"dyConsumed:" + dyConsumed + ",dxUnconsumed:" + dxUnconsumed + ",dyUnconsumed:" +
dyUnconsumed + ",offsetInWindow:" + offsetInWindow);
return getScrollingChildHelper().dispatchNestedScroll(dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed, offsetInWindow);
}
@Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
Log.i(Tag, "dispatchNestedPreScroll:dx" + dx + ",dy:" + dy + ",consumed:" + consumed + ",offsetInWindow:" + offsetInWindow);
return getScrollingChildHelper().dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
@Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
Log.i(Tag, "dispatchNestedFling:velocityX:" + velocityX + ",velocityY:" + velocityY + ",consumed:" + consumed);
return getScrollingChildHelper().dispatchNestedFling(velocityX, velocityY, consumed);
}
@Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
Log.i(Tag, "dispatchNestedPreFling:velocityX:" + velocityX + ",velocityY:" + velocityY);
return getScrollingChildHelper().dispatchNestedPreFling(velocityX, velocityY);
}
private NestedScrollingChildHelper getScrollingChildHelper() {
if (mScrollingChildHelper == null) {
mScrollingChildHelper = new NestedScrollingChildHelper(this);
mScrollingChildHelper.setNestedScrollingEnabled(true);
}
return mScrollingChildHelper;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(),getMeasuredHeight()+((MyNestedScrollParent)getParent()).getTopViewHeight());
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lmj.com.mynestscroll.MainActivity"> <com.lmj.com.mynestscroll.view.MyNestedScrollParent
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0f0"
android:clickable="true"
android:orientation="vertical"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
> <TextView
android:id="@+id/tv_search"
android:layout_width="match_parent"
android:layout_height="100dp"
android:gravity="center"
android:padding="20dp"
android:text="搜索" /> <LinearLayout
android:id="@+id/ll_other"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:orientation="vertical"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#30ffffff"
android:drawablePadding="10dp"
android:gravity="center_vertical"
android:padding="10dp"
android:text="任何地方"
android:textColor="#fff" /> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="#30ffffff"
android:drawablePadding="10dp"
android:padding="10dp"
android:text="任何时间"
android:textColor="#fff" /> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="#30ffffff"
android:drawablePadding="10dp"
android:padding="10dp"
android:text="房客"
android:textColor="#fff" /> </LinearLayout>
</LinearLayout> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f0f"
android:text="@string/topStr" /> <com.lmj.com.mynestscroll.view.MyNestedScrollChild
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="1231231231312"
/> </com.lmj.com.mynestscroll.view.MyNestedScrollChild> <!--<com.lmj.com.mynestscroll.MyRecycleView-->
<!--android:id="@+id/id_recyclerview"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent">--> <!--</com.lmj.com.mynestscroll.MyRecycleView>--> </com.lmj.com.mynestscroll.view.MyNestedScrollParent> </RelativeLayout>
NestedScrollingChild和NestedScrollingParent之间的部分,在滑动时会悬浮在顶部 而RecycleView 本身已经实现了NestedScrollingChild 我们在使用RecycleView的时候 需要重写onMeasure方法
public class MyRecycleView extends RecyclerView {
public MyRecycleView(Context context) {
super(context);
}
public MyRecycleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
setMeasuredDimension(getMeasuredWidth(),getMeasuredHeight()+((MyNestedScrollParent)getParent()).getTopViewHeight());
}
}
重新设定RecycleView的高度
NestedScrollView嵌套RecycleView 滑动 实现上滑隐藏 下滑显示头部效果的更多相关文章
- js监听事件 上滑消失下滑出现的效果 触摸与手势事件
https://www.w3cmm.com/javascript/touch.html //触摸与手势事件连接tinyscrollbar //方法1var _this = $('#fabu');var ...
- iOS 上滑隐藏导航,下滑显示导航,仿斗鱼导航效果
UItableView或 UIcollectionView 都是继承UIScrollView 滑动的时候,判断是上滑还是下滑 使用 UIScrollView 的代理方法 func scrollView ...
- NestedScrollView嵌套RecycleView发生的小问题
1.解决方法:嵌套滑动不激活. recycleView.setNestedScrollingEnable(false); 这样做有个弊端,RecycleView的item会一次性加载完,不管是否显示, ...
- uwp - 上滑隐藏导航栏下滑显示
原文:uwp - 上滑隐藏导航栏下滑显示 好久没写博客了,因为忙着工作.昨天周末填坑需要做一个上滑列表数据时隐藏导航栏下滑时显示的效果,下面分享一下我的做法,希望能给你带来帮助. 思路是通过判断滚动条 ...
- js判断手指的上滑,下滑,左滑,右滑,事件监听
原理:1:当开始一个touchstart事件的时候,获取此刻手指的横坐标startX和staerY: 2:当触发touchmove事件的时候,再获取此时手指的横坐标moveEndX和纵坐标moveEn ...
- vue中使用触摸事件,上滑,下滑,等
第一步,下载一个包 npm install kim-vue-touch -s 在当前项目中下载包 第二部 import vueTouch from 'kim-vue-touch' Vue.use(vu ...
- Android 浮动按钮+上滑隐藏按钮+下滑显示按钮
1.效果演示 1.1.关注这个红色的浮动按钮 . 可以看到,上滑的时候浮动按钮消失,因为用户迫切想知道下面的东西,而不是回到顶部. 当下滑的时候,用户想回到原来的位置,就可以点击浮动按钮,快速回到顶部 ...
- Material Design之CoordinatorLayout+AppBarLayout实现上滑隐藏ToolBar
ok,今天继续更新Material Design系列!!! 废话不说,先看看效果图吧: 好了,现在来讲讲上图是怎么实现的吧!讲之前先讲讲几个控件: CoordinatorLayout 该控件也是De ...
- iOS---实现简书和知乎的上滑隐藏导航栏下拉显示导航栏效果
因为自己用简书和知乎比较多,所以对其导航栏的效果比较好奇,自己私下里找资料实现了一下.这个效果的关键点在于下方可供滑动的内容的便宜距离inset的改变,以及滑动的scrollview代理的执行,废话不 ...
随机推荐
- 每天一个Linux命令(06)--rmdir命令
终于忙完了公司的事,可以安静的充充电了. 今天学习一下Linux中命令:rmdir 命令,rmdir是常用的命令,该命令的功能是删除空目录,一个目录被删除之前必须是空的.(注意,rm -r dir 命 ...
- Laravel生命周期
如果你对一件工具的使用原理了如指掌,那么你在用这件工具的时候会充满信心! 一旦用户(浏览器)发送了一个HTTP请求,我们的apache或者nginx一般都转到index.php,因此,之后的一系列步骤 ...
- 2017-3-2 C# WindowsForm 中label标签居中显示
有时候label标签要输出 label.text=""; 的语句,那么要把这个语句居中显示 1.要取消他的Autosize的值 2.拉大这个框,设置里面的文本的TextAlign ...
- Docker存储驱动之OverlayFS简介
简介 OverlayFS是一种和AUFS很类似的文件系统,与AUFS相比,OverlayFS有以下特性: 1) 更简单地设计: 2) 从3.18开始,就进入了Linux内核主线: 3) 可能更快一些. ...
- 20ms Ac Code
Rectangle Aread C Code #include <stdio.h> int computeArea(int A,int B,int C,int D,int E,int F, ...
- vbs文件小技巧
vbs文件介绍: VBS是基于Visual Basic的脚本语言.VBS的全称是:Microsoft Visual Basic Script Editon.(微软公司可视化BASIC脚本版). 可以新 ...
- koahub.js 0.09 发布,新增钩子机制
koahubjs发布0.09 新增钩子机制添加钩子机制,控制器钩子和函数钩子修复自动加载bug,实现除自动加载导出的default外,还能自动加载其他的方法记koahubjs钩子开发过程在使用koah ...
- java构造函数使用方法总结
使用构造器时需要记住: 1.构造器必须与类同名(如果一个源文件中有多个类,那么构造器必须与公共类同名) 2.每个类可以有一个以上的构造器 3.构造器可以有0个.1个或1个以上的参数 4.构造器没有返回 ...
- rem 结合 scss 移动端自适应 初级入门demo
首先说明 本篇 内容 适合初级使用 rem 开发移动端 自适应 公式计算 推导过程, 高手绕路. 目标尺寸 = rem * 根字体大小 Px = rem * (html根字体px) 根字体大 ...
- XML配置文件的命名空间与Spring配置文件中的头
一直以来,写Spring配置文件,都是把其他配置文件的头拷贝过来,最多改改版本号,也不清楚哪些是需要的,到底是干嘛的.今天整理一下,拒绝再无脑copy. 一.Spring配置文件常见的配置头 < ...