今天看到百度手机助手首页上的滑动效果非常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开源项目第一篇——个性化控件(View)篇 收藏的

Android开源项目第一篇——个性化控件(View)篇收藏的本文为那些不错的Android开源项目第一篇——个性化控件(View)篇,主要介绍Android上那些不错个性化的Vi

源码分析Fragmentd的BackStack管理过程

转载:http://blog.csdn.net/bigconvience/article/details/305020711.Fragment基本用法为了管理Activity中的fragments,需要调用Activity中的getFragmentManager()方法。因为FragmentMana

RecyclerView基本使用

RecyclerView是android5.0推出的新的控件,官方给出的说明是:RecyclerViewisamoreadvancedandflexibleversionofListView.Thiswidgetisacontainerforlargesetsofviewsthatcanberecycledandscrolle

仿百度动态Android源码,Android 仿百度手机助手首页滑动效果相关推荐

  1. [Android源码]Android源码之高仿飞鸽传书WIFI热点搜索与创建(一)

    (本文详情来源:android源码 http://www.eoeandroid.com/thread-296427-1-1.html   转载请注明出处!)  [Android源码分享]飞鸽传书的An ...

  2. android 快传 源码_安卓APP仿茄子快传源码,Android项目源码类似茄子快传的快传项目包括服务端...

    适用范围:安卓APP仿茄子快传源码,Android项目源码类似茄子快传的快传项目包括服务端 演示地址:(以截图为准) 运行环境:Android+PC+web 其他说明: 本项目是一个基于安卓的类似茄子 ...

  3. 糗事百科 android源码,Android高仿糗事百科(含服务端)

    Android高仿糗事百科(含服务端) 积分: 23 智慧币 积分: 3 智慧币 [1.00元 ] 包含内容: 源码,全套工具 详情描述 如遇视频不清晰,请最大化观看演示 以下仅列出部分功能,全部功能 ...

  4. android 快传 源码_app源码之-仿茄子快传源码,Android项目源码类似茄子快传的快传项目包括服务端...

    商品属性 品牌其他 语言PHP 数据库 移动端无 大小48 MB 规格无 授权无 源文件无 安装环境 安装服务 主机类型 伪静态 操作系统 安装方式 web服务 商品介绍 本项目是一个基于安卓的 ...

  5. ThinkPHP php 仿千图网源码_仿百度网盘文件分享dzzoffice网盘系统源码_PHP

    声明:"本专区源码来源于各大收费资源站转载 ,都是花钱买的,但是站内不测试 ,仅供学习参考,请勿用作商业用途,签到投稿即可获得积分下载!" 本网盘修复的焦点功效 1.断点续传功效. ...

  6. as 关联 android源码,android studio 2.x以上关联源码

    android studio (以下称为as)的 sdk 一升级,往往发现查看不了源码的,即使有两个选择(Download / Refresh(if already downloaded)),但是发现 ...

  7. 健身android源码,Android项目源码运动健身项目

    [实例简介] 本项目是健身项目Android应用,本软件包含健身项目和计时运动,更多的了解运动前和运动后需要注意的事项和禁忌,也包含了许多健康的健身习惯的文档,应该说这个应用太强大了,用到技术,项目中 ...

  8. php仿微信朋友圈源码,Android开发仿微信发朋友圈浏览图片效果实例代码

    这篇文章主要介绍了Android仿微信发朋友圈浏览图片效果的相关资料,需要的朋友可以参考下 先看一下效果吧: 下面就来说一下具体怎么实现的: 实现思路1.首先我们要获取数据源,数据源就是我们的每条说说 ...

  9. android简书app源码,仿简书APP源码(android)

    [实例简介] [实例截图] [核心代码] package com.yidou.wandou.example_33.ui; import android.content.Context; import ...

最新文章

  1. windows启动mysql8服务_MySQL8.0服务启动(windows10)
  2. tomcat,JVM内存设置
  3. windown下linux子系统的安装和卸载
  4. WebDriver自动化测试工具(3)---PhantomJS的使用
  5. Spring注解编程基石(二)
  6. 为什么map对象不能使用stl中的sort函数
  7. JFinal 1.5 发布,JAVA极速WEB+ORM框架
  8. 使用Spring Boot和Project Reactor处理SQS消息-第2部分
  9. Python连接MySQL数据库(pymysql),DataFrame写入 MySQL(create_engine)- Python代码
  10. su、sudo、sudo su、sudo -i的用法和区别
  11. html 时钟怎样居中,怎么用css3做时钟刻度
  12. 合成器插件Serum 1.23b7绿化版亲测有效
  13. C#生成随机姓名 单姓 复姓
  14. 输入1到100带圈字符Ⓢ你以为很容易的/其实特容易翻车的需求
  15. wajueji.php,独家解析:为什么说斗山DX55-9C是5吨小挖掘机中的新机皇
  16. 植被指数-RVI、NDVI、DVIEVI、GVI、PVI、EVI
  17. RISC-V嵌入式开发入门篇2:RISC-V汇编语言程序设计(上)
  18. 麻省理工公开课人工智能笔记六
  19. FFMPEG AvFilter使用实例(实现视频缩放,裁剪,水印等)
  20. Android 中的代码混淆

热门文章

  1. cad脚本合适_AutoCAD小秘密045:动作录制器,穷人版的脚本
  2. 在win10自带Ubuntu16下搭建环境使用CLion2018进行C++开发
  3. OPPO手机云便签同步后在哪里能找回来啊
  4. 四、日志系统:log文件夹下的log.h和log.cpp——TinyWebServer
  5. 如何用python代替微信接受消息,查看撤回消息(itchat实现)
  6. 多vlan局域网下网络打印机驱动安装
  7. GLSL 中文手册(转载)
  8. 在maya中实现逼真的履带效果
  9. 电脑屏幕视力保护色 RGB(204,232,207)
  10. JAVA计算机毕业设计忻府区饭中有豆粮油销售系统Mybatis+源码+数据库+lw文档+系统+调试部署