今天看到百度手机助手首页上的滑动效果非常nice,主要功能归结为:

1、当手指上划时,顶部搜索栏随手指移动距离而缩小到隐藏,隐藏后内容还是可以继续移动

2、手指下滑时,当显示内容达到第一个时,顶部搜索栏逐渐变大显示

自己实现用到的知识:

1、android事件传递机制:捕获到手指移动事件后,根据移动的方向与功能栏的高度对功能栏大小进行修改 。由于listview与功能栏高度要同时移动,需要重写了dispatchTouchEvent方法,直接调用this.onTouchEvent(ev);进行所有事件的捕捉分析

2、自定义viewgroup:测量view高度

额外添加的功能:

功能栏高度<=1/2时,会自动隐藏

功能栏高度>1/2时,会自动改变到最大值

代码实现在MotionEvent.ACTION_UP

效果展示,录像工具太卡,将就着看吧:

本来想做成一个通用的工具类,工作比较忙就偷懒了,在ScrollHideLayout类中定义了两个常量,直接写死了需要被捕获滑动事件与改变大小的viewID,使用时可以自己再次封装,或者直接修改ID,虽然不推荐,但是省事哈!!!

private int scrollViewId = R.id.scrollView; //滑动后变化功能栏的viewid

private int changeViewId = R.id.changeView;// 大小随之变化的viewid

完整代码:

1、自定义的viewgroup

package com.example.materialtest.widget;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.RectF;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout; import com.example.materialtest.R; /**
* 滑动隐藏控件
*
*
*/
public class ScrollHideLayout extends LinearLayout implements OnScrollListener { private static final String TAG = ScrollHideLayout.class.getSimpleName(); private int scrollViewId = R.id.scrollView;
private int changeViewId = R.id.changeView; private int changeViewMaxHeight;
private PointF touchPoint = new PointF(); private View changeView;
private AbsListView scrollView; private RectF scrollViewRect = new RectF(); public ScrollHideLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public ScrollHideLayout(Context context) {
this(context, null);
} public ScrollHideLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int len = getChildCount(); if (null == changeView || null == scrollView) {
for (int i = 0; i < len; i++) {
View child = getChildAt(i);
// 滑动控件
if (child.getId() == scrollViewId && child instanceof AbsListView) {
scrollView = (AbsListView) child;
setScrollViewRect();
}
if (child.getId() == changeViewId) {
changeView = child;
changeView.setMinimumHeight(0); changeViewMaxHeight = changeView.getMeasuredHeight();
} }
} else {
// 重新计算滚动控件的位置
setScrollViewRect();
} Log.i(TAG, "find scrollview and changeView :" + scrollViewId + "," + changeViewId);
Log.i(TAG, "scrollview rect:" + changeView.getLayoutParams().getClass().getCanonicalName()); if (null == changeView || null == scrollView) {
throw new IllegalArgumentException("could not foud changeView or scrollView");
}
} private void setScrollViewRect() {
// 获取滚动控件的范围
float left = ViewCompat.getX(scrollView);
float top = ViewCompat.getY(scrollView);
float right = left + scrollView.getMeasuredWidth();
float bottom = top + scrollView.getMeasuredHeight(); scrollViewRect.left = left;
scrollViewRect.top = top;
scrollViewRect.right = right;
scrollViewRect.bottom = bottom;
} @Override
public boolean onTouchEvent(MotionEvent ev) { if (!isScrollViewTouch(ev)) {
return false;
} final android.view.ViewGroup.LayoutParams params = changeView.getLayoutParams(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN:
touchPoint.x = ev.getX();
touchPoint.y = ev.getY();
break; case MotionEvent.ACTION_MOVE: int height = params.height; // 滑动控件移动事件
float distance = ev.getY() - touchPoint.y; // 最大高度,不能向下拖动
if (height >= changeViewMaxHeight && distance > 0) {
touchPoint.y = ev.getY();
break;
}
// 已经隐藏 不能向上滑动
if (height <= 0 && distance < 0) {
touchPoint.y = ev.getY();
break;
} // listview到达顶部才可以向下拖动
if (distance > 0 && scrollView.getFirstVisiblePosition() != 0) {
touchPoint.y = ev.getY();
break;
} height = Math.round(height + distance); if (height > changeViewMaxHeight) {
height = changeViewMaxHeight;
} if (height <= 0 && distance < 0) {
height = 0;
// TODO onhide
} params.height = height; changeView.requestLayout(); touchPoint.x = ev.getX();
touchPoint.y = ev.getY(); break; case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: // 高度超过一半,自动隐藏
int[] values = null;
// 向上滑动,剩余位置不足一半
if (params.height <= changeViewMaxHeight / 2) {
values = new int[] { params.height, 0 };
} else {
values = new int[] { params.height, changeViewMaxHeight };
} if (null != values) {
ValueAnimator anim = ObjectAnimator.ofInt(changeView, "translationY", values);
anim.addUpdateListener(new AnimatorUpdateListener() { @Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
params.height = value;
changeView.requestLayout();
}
});
anim.setDuration(250);
anim.setTarget(changeView);
anim.start();
} break;
} return true;
} @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// 直接拦截事件
this.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
} private boolean isScrollViewTouch(MotionEvent ev) { float x = ev.getX();
float y = ev.getY();
return (x >= scrollViewRect.left && x <= scrollViewRect.right) && (y >= scrollViewRect.top && y <= scrollViewRect.bottom);
} /**
* @return Whether it is possible for the child view of this layout to
* scroll up. Override this if the child view is a custom view.
*/
public boolean canChildScrollUp() {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (scrollView instanceof AbsListView) {
final AbsListView absListView = (AbsListView) scrollView;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0).getTop() < absListView.getPaddingTop());
} else {
return ViewCompat.canScrollVertically(scrollView, -1) || scrollView.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(scrollView, -1);
}
} @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub } @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub }
}

Android 仿百度手机助手首页滑动效果的更多相关文章

  1. Android仿360手机卫士悬浮窗效果

    请看下图:                         首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下 ...

  2. Android静默安装实现方案,仿360手机助手秒装和智能安装功能

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/47803149 之前有非常多朋友都问过我.在Android系统中如何才干实现静默安装 ...

  3. 完美逆向百度手机助手5.0底部菜单栏 - Android Tabhost 点击动画

    先看看百度手机助手5.0的样子: 发现他是用一个CustomTabHost.java来实现底部TabHost点击效果的,很漂亮,点击Tab的时候文字会上跑,图片会从底部跑出来的一个小动画. 下面我用自 ...

  4. Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果

    大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我说几句不相干的废话. 不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多 ...

  5. 安卓app上传到应用宝、360手机助手、小米应用商店、百度手机助手/安卓市场/91助手

    1.小米应用商店 小米开放平台网站:https://account.xiaomi.com 注册帐号教程地址:http://dev.xiaomi.com/doc/?p=90 应用提交流程:http:// ...

  6. Bdsyn百度手机助手是何物,它是怎样神不知鬼不觉地安装到你的电脑里的?

    [电脑软件管理中Bdsyn手机助手的问题]Bdsyn手机助手 is developed by Baidu, Inc. and is used by 10 users of Software Infor ...

  7. Android 仿百合网超火爆社交app首页滑动效果

    探探,百合网等神器的首页有一个相册加载个控件,通过左滑右滑加载新的照片,同时左滑丢弃这个照片,右滑则表明对这个照片感兴趣. 这个效果是怎么实现的呢? 1,Android3.0以后控件中增加了setTr ...

  8. Android 仿百度网页音乐播放器圆形图片转圈播放效果

    百度网页音乐播放器的效果  如下 : http://www.baidu.com/baidu?word=%E4%B8%80%E7%9B%B4%E5%BE%88%E5%AE%89%E9%9D%99& ...

  9. Android 桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果

    首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下类似的效果. 先谈一下基本的实现原理,这种桌面悬浮窗的效果很 ...

随机推荐

  1. MySQL 50题练习

    表名和字段 –1.学生表 Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_id ...

  2. JasperReports入门教程(一):快速入门

    JasperReports入门教程(一):快速入门 背景 现在公司的项目需要实现一个可以配置的报表,以便快速的适应客户的需求变化.后来在网上查资料发现可以使用JasperReports + Jaspe ...

  3. CSS躬行记(7)——合成

    在图形编辑软件中,可以按特定地方式处理不同图层的合成,最新的CSS规范也引入了该功能,并提供了mix-blend-mode和background-blend-mode两个属性.混合模式(blendin ...

  4. MinIO 的分布式部署

    目录 1 前言 2 分布式存储可靠性常用方法 2.1 冗余 2.2 校验 3 MinIO存储机制 3.1 概念理解 3.2 纠删码EC(Erasure Code) 3.3 存储形式 4 部署实践 4. ...

  5. python实现逻辑回归

    首先得明确逻辑回归与线性回归不同,它是一种分类模型.而且是一种二分类模型. 首先我们需要知道sigmoid函数,其公式表达如下: 其函数曲线如下: sigmoid函数有什么性质呢? 1.关于(0,0. ...

  6. javescrip内嵌样式与外联样式怎么做?

    对于前端初学者,个人JS样式常用的有两种:内嵌样式 ,外联样式:下面通过一个简单的鼠标点击出现设定的验证数字为例进行演示: 先看下效果: 鼠标点击前效果: 鼠标点击后效果: 图中的这个ojbk是我js ...

  7. hdu_2391 Filthy Rich DP

    Filthy Rich Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  8. 【JAVA基础】07 面向对象2

    1. 代码块的概述和分类 面试的时候会问,开发不用或者很少用 代码块概述 在Java中,使用 {} 括起来的代码被称为代码块. 代码块分类 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态 ...

  9. Highcharts的自适应DOM或者DIV,JS方法实现

    那我们就按照官网的一分钟极速入门代码来说 // 图表配置 var options = { chart: { type: 'bar' //指定图表的类型,默认是折线图(line) }, title: { ...

  10. VS Code 全部快捷键一览表(巨TM全)

    常用 General 按 Press 功能 Function Ctrl + Shift + P,F1 显示命令面板 Show Command Palette Ctrl + P 快速打开 Quick O ...