Android_滚动状态ScrollView实现标题的悬浮和渐隐
来源:互联网 发布:1325雕刻机参数算法 编辑:程序博客网 时间:2024/05/26 12:04
最近项目需求,需要实现标题的悬浮和渐隐渐变….于是故事开始了
1,代码接受后,业务逻辑复杂,最好的完成就是基于现在XML和activity 做最少的改动实现,所以网上的demo,以及5.0后的Coordinglayout 我就放弃了,这样的改动及时能实现,也要改太多东西,
2,于是还是自己实现下吧,下图是预览,GIF 录制不了..哎
上滑动的时候titlebar 渐出
下滑动的时候titlebar 渐入
这里是初始进入的样子
这里是慢慢画出的样子
这里是全部画出的样子
最后是渐入的样子,
==========================================================
OK,基于不是自己实现的代码,最加单的实现就是改变最外层布局为FrameLayout + include进来titlebarbar
初始化的时候把titlebar隐藏,注意这里的隐藏不是GONE掉,而是把titlebar设置到屏幕外面,很简单,大家都会,这里就不浪费时间描述了
发现短短的三句代码不到 我们的功能已经实现了一半了对不对
首先描述下实现思路
- 根据现在的代码状态,基于scrollview的滑动,改变titlebar的位置
- 由于scrollview给我们提供了一个私有的onScrollChanged方法,注意
如果你用AS自己设置一个onScrollChanged方法,会提示你,低版本的API不能用而且会crash,所以我们自己重写scrollview 提供接口给外界activity用 - 然后我们重写scrollview的ontouch方法,模拟出scrollview的滑动状态
public interface OnScrollListener { int SCROLL_STATE_IDLE = 0; int SCROLL_STATE_TOUCH_SCROLL = 1; int SCROLL_STATE_FLING = 2; void onBottomArrived(); void onScrollStateChanged(ATListenedScrollView view, int scrollState); void onScrollChanged(int l, int t, int oldl, int oldt); }
这里是ontouch方法
@Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: inTouch = true; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: inTouch = false; lastT = getScrollY(); checkStateHandler.removeMessages(CHECK_STATE); checkStateHandler.sendEmptyMessageDelayed(CHECK_STATE, 5); break; default: break; } return super.onTouchEvent(ev); }
完整的scrollview 代码如下,直接用就可以获取 坐标的变化和scrollview的滑动状态
public class ATListenedScrollView extends ScrollView { private static final int CHECK_STATE = 0; private OnScrollListener onScrollListener; private boolean inTouch = false; private int lastT = 0; public ATListenedScrollView(Context context) { super(context); } public ATListenedScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public ATListenedScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: inTouch = true; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: inTouch = false; lastT = getScrollY(); checkStateHandler.removeMessages(CHECK_STATE); checkStateHandler.sendEmptyMessageDelayed(CHECK_STATE, 5); break; default: break; } return super.onTouchEvent(ev); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (onScrollListener == null) { return; } if (inTouch) { if (t != oldt) { onScrollListener.onScrollStateChanged(this, OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); } } else { if (t != oldt) { onScrollListener.onScrollStateChanged(this, OnScrollListener.SCROLL_STATE_FLING); lastT = t; checkStateHandler.removeMessages(CHECK_STATE); checkStateHandler.sendEmptyMessageDelayed(CHECK_STATE, 5); } } onScrollListener.onScrollChanged(l, t, oldl, oldt); } public void setOnScrollListener(OnScrollListener onScrollListener) { this.onScrollListener = onScrollListener; } public interface OnScrollListener { int SCROLL_STATE_IDLE = 0; int SCROLL_STATE_TOUCH_SCROLL = 1; int SCROLL_STATE_FLING = 2; void onBottomArrived(); void onScrollStateChanged(ATListenedScrollView view, int scrollState); void onScrollChanged(int l, int t, int oldl, int oldt); } private WeakRefHandler checkStateHandler = new WeakRefHandler(this); /** * WeakReference handler */ static class WeakRefHandler extends Handler { WeakReference<ATListenedScrollView> atListenedScrollViewWeakReference; WeakRefHandler(ATListenedScrollView atListenedScrollView) { atListenedScrollViewWeakReference = new WeakReference<ATListenedScrollView>(atListenedScrollView); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); ATListenedScrollView atListenedScrollView = atListenedScrollViewWeakReference.get(); if (atListenedScrollView.lastT == atListenedScrollView.getScrollY()) { atListenedScrollView.onScrollListener.onScrollStateChanged(atListenedScrollView, OnScrollListener.SCROLL_STATE_IDLE); if (atListenedScrollView.getScrollY() + atListenedScrollView.getHeight() >= atListenedScrollView.computeVerticalScrollRange()) { atListenedScrollView.onScrollListener.onBottomArrived(); } } } }}
现在我们的scrollview都提供好了,工作又完成了2/3
剩下的代码就是activity里面的滑动监听,改变titlebar的位置,顺道加一个渐变动画soeasy
Duang 来了
private void initTitleScroll() { scrollView.setOnScrollListener(new ATListenedScrollView.OnScrollListener() { @Override public void onBottomArrived() { //如果scrollview滚到底部并且是静止状态,显示titlebar if (isIDLE) { hotelTitelViewLayoutParams.topMargin = 0; hotelTitelView.setLayoutParams(hotelTitelViewLayoutParams); hotelTitelView.setAlpha(1.F); } } @Override public void onScrollStateChanged(ATListenedScrollView view, int scrollState) { // 给我们定义的是否是滚动和滑翔的状态变量赋值 isFilling = scrollState == SCROLL_STATE_FLING; isIDLE = scrollState == SCROLL_STATE_IDLE; } @Override public void onScrollChanged(int l, int y, int oldl, int oldY) { // 滑动监听的回调,如果是静止状态,并且y是0,这时候隐藏titlebar if (isIDLE && 0 == y) { hotelTitelViewLayoutParams.topMargin = -hotelTitleHeight; hotelTitelView.setLayoutParams(hotelTitelViewLayoutParams); hotelTitelView.setAlpha(0); return; } // 如果是滑动状态,并且titlebar的topmarin是0,显示titlebar if (isFilling && hotelTitelViewLayoutParams.topMargin == 0) { hotelTitelView.setAlpha(1.F); return; } else if (isFilling && hotelTitelViewLayoutParams.topMargin < 0) { hotelTitelViewLayoutParams.topMargin = -hotelTitleHeight; hotelTitelView.setAlpha(0); hotelTitelView.setLayoutParams(hotelTitelViewLayoutParams); return; }//特殊情况判断完毕,这是在滑动的时候dy是偏移量,根据便宜量计算出titlebar的alpha值,和改变titlebar距离顶部的位置,ok到此全部实现, int dY = oldY - y; hotelTitelView.setAlpha(ATUtils.getAlphaScale(hotelTitleHeight - Math.abs(hotelTitelViewLayoutParams.topMargin), hotelTitleHeight)); if (hotelTitelViewLayoutParams.topMargin > 0) { hotelTitelViewLayoutParams.topMargin = 0; hotelTitelView.setLayoutParams(hotelTitelViewLayoutParams); return; } if (dY < 0 && hotelTitelViewLayoutParams.topMargin == 0) { // up slide edge return; } else if (dY > 0 && hotelTitelViewLayoutParams.topMargin == -hotelTitleHeight) { // down slide edge return; } if (hotelTitelViewLayoutParams.topMargin >= -hotelTitleHeight && hotelTitelViewLayoutParams.topMargin <= 0) { hotelTitelViewLayoutParams.topMargin = hotelTitelViewLayoutParams.topMargin - dY; } else if (hotelTitelViewLayoutParams.topMargin > 0) { hotelTitelViewLayoutParams.topMargin = 0; } else if (hotelTitelViewLayoutParams.topMargin < -hotelTitleHeight) { hotelTitelViewLayoutParams.topMargin = -hotelTitleHeight; } hotelTitelView.setLayoutParams(hotelTitelViewLayoutParams); } }); }
关键代码和自定义的scrollview全部在这里,因为直接写项目里面的所以没有demo可上传,如果有类似效果直接copy上面代码即可
当有需求改变,但前期代码不是你自己的情况下,尽可能的做的改动最少来实现,尤其是业务逻辑部分,根本不用关心,只需要扩展即可,如果找github或者其他demo 如果是基于Coordinglayout等等,需要改变的就不是这么一点了
- Android_滚动状态ScrollView实现标题的悬浮和渐隐
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android - 小功能 - 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- swift纯代码创建view
- assign,retain,copy对比
- JavaScript DOM中 改变样式属性,实现动画效果 2
- NSLayoutConstraint
- Markdown编辑器使用说明
- Android_滚动状态ScrollView实现标题的悬浮和渐隐
- swift中一个类定义一个属性必须初始化,如果不想初始化可以加?
- 极光推送接收不到消息
- APP UI屏幕适配
- pytesser 的使用
- CSS float浮动的深入研究、详解及拓展 一 一 一 一 一 一 一 一
- office2016 下载和激活
- LeetCode 70. Climbing Stairs(爬楼梯)
- NYOJ Fibonacci数