前言

我K。今天竟然是情人节。对于资深的单身狗来说,简直是个噩耗,今天注定是各种秀恩爱。心塞中。。

。。

话题到此结束,管他什么情人节,今天给大家带来的是一个浮层的上下滑动,浮层滑动时分三种状态:所有显示、显

示一半、隐藏。可在浮层中加入ListView,GirdView,ImageView等等View。

详细的效果看以下的GIF图:

效果解说

1、在上面的浮层中我们能够看到存放着一个ListView。并能进行上下滚动,也就是说浮层的Touch事件须要在适

当的时候进行拦截,不传递给子View。

这时须要重写onInterceptTouchEvent()和onTouch()方法。

onInterceptTouchEvent和onTouch的介绍请參看以下:

1、onInterceptTouchEvent()是用于处理事件(类似于预处理。当然也能够不处理)并改变事件的传递方向,也就是

决定是否同意Touch事件继续向下(子控件)传递。一但返回True(代表事件在当前的viewGroup中会被处理),则向

下传递之路被截断(全部子控件将没有机会參与Touch事件),同一时候把事件传递给当前的控件的onTouchEvent()处

理;返回false。则把事件交给子控件的onInterceptTouchEvent()。

2、onTouchEvent()用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。也就是说在当前控件在处

理完Touch事件后,是否还同意Touch事件继续向上(父控件)传递,一但返回True,则父控件不用担心自己来处理

Touch事件。返回true,则向上传递给父控件(注:可能你会认为是否消费了有关系吗。反正我已经针对事件编写了

处理代码?答案是有差别。比方ACTION_MOVE或者ACTION_UP发生的前提是一定以前发生了ACTION_DOWN,假设你没有

消费ACTION_DOWN,那么系统会觉得ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。

2、在上图中能够看出。当进行上下滚动时具有滚动效果,能够通过下面代码实现:

ObjectAnimator anim=ObjectAnimator.ofFloat(this, "translationY", values);

实现原理

实现的原理事实上非常easy,我们所要做的就是在onInterceptTouchEvent和onTouch两个事件处理的方法中进行处理。

onInterceptTouchEvent的任务是推断何时拦截事件。交由onTouch处理。何时由子View进行事件处理。

依据上图能够非常清楚知道onInterceptTouchEvent所要做的工作。在onTuch的中最基本的操作是在获取滑动时的

MotionEvent.ACTION_MOVE中进行动画的处理。

到此为止仅仅说讲解了两个事件处理方法该做写什么。在图中能够看出。滑动时主要有三种状态。各自是所有显示

、显示一半、隐藏。

所有显示:当浮层所有显示时。这时浮层视图不应该继续向上滚动,这时须要在onInterceptTouchEvent中将事

件传递给它的子View进行处理;当向下滑动时,须要进行向下移动的动画处理,滑动一次。这时的浮层视图应该显示

一半。

显示一半:当浮层显示一半时。这时进行向上滑动时须要运行向上移动的动画处理,向下滑动时也一样。进行移

动的动画处理。进行隐藏浮层。

隐藏:当浮层进行隐藏时。能够通过点击对应的点击事件,使浮层从底部向上移动,并移动一半。

代码

以上是大体的思路。详细实现请參看以下的代码。

public class FloatingLayerView extends LinearLayout implements OnTouchListener {/*** 视图显示类型。

*/ private int type=ALL; /** * 浮层的高度。 */ private int floating_height; /** * 浮层的宽度 */ private int floating_width; /** * 滑动高度 */ private float move_height; /** * 是否向下滑动。交由onTouch事件处理。

*/ private boolean isCanHide=false; /** * 是否进行动画 */ private boolean isCanAnimation=false; /** * 触发拦截触摸事件时的坐标点。 * 按下: * interceptTouch_X:按下时的X坐标点。 * interceptTouch_Y:按下时的Y坐标点。

* 滑动: * interceptMove_X:滑动时的X坐标点。 * interceptMove_Y:滑动时的Y坐标点。 * 距离: * interceptTouch_Move_X:从按下到滑动之间的距离(横向滑动) * interceptTouch_Move_Y:从按下到滑动之间的距离(纵向滑动) * 滑动距离: * moveLength:依据此值推断是否进行了滑动。

*/ private float interceptTouch_X; private float interceptTouch_Y; private float interceptMove_X; private float interceptMove_Y; private float interceptTouch_Move_X; private float interceptTouch_Move_Y; private int moveLength=10; /** * 触发触摸事件时的坐标点 * down_X:按下时的X坐标点。 * down_Y:按下时的Y坐标点。

* move_X:移动时的X坐标点。

* move_Y:移动时的Y坐标点。

* down_move_X:横向滑动的距离。 * down_move_Y:纵向滑动的距离。 */ private float down_X; private float down_Y; private float move_X; private float move_Y; private float down_move_X; private float down_move_Y; /** * 定义三种浮层显示类型 * 0:不显示 1:显示一半 2:所有显示 */ private static final int NONE=0; private static final int HALF=1; private static final int ALL=2; public FloatingLayerView(Context context, AttributeSet attrs) { super(context, attrs); setOnTouchListener(this); } public FloatingLayerView(Context context) { super(context); } @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if(hasWindowFocus){ floating_width=getWidth(); floating_height=getHeight(); /** * 每次滑动的距离是当前View宽度的三分之中的一个。 */ move_height=floating_height/3; } super.onWindowFocusChanged(hasWindowFocus); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { /** * 当按下时获取x,y的坐标点。 */ case MotionEvent.ACTION_DOWN: interceptTouch_X = ev.getX(); interceptTouch_Y = ev.getY(); isCanAnimation=true; break; /** * 当滑动时操作例如以下: * 1、获取滑动距离 * 2、推断向上滑动还是向下滑动 * 3、向上滑动时 * 4、向下滑动时,推断当前显示方式: * (1)、显示一半时。交由onTouch事件处理。 * (2)、所有显示时,是否向下滑动交由当前View的子View处理, * 是否交由onTouch事件处理。

*/ case MotionEvent.ACTION_MOVE: interceptMove_X = ev.getX(); interceptMove_Y = ev.getY(); interceptTouch_Move_X = Math .abs(interceptTouch_X - interceptMove_X); interceptTouch_Move_Y = Math .abs(interceptTouch_Y - interceptMove_Y); /** * 向下滑动 */ if(interceptMove_Y>interceptTouch_Y&&interceptTouch_Move_Y>moveLength&&interceptTouch_Move_Y>interceptTouch_Move_X){ return isDounTransferOnTouch(); } /** * 向上滑动 */ if(interceptTouch_Y>interceptMove_Y&&interceptTouch_Move_Y>moveLength&&interceptTouch_Move_Y>interceptTouch_Move_X){ return isUpTransferOnTouch(); } break; case MotionEvent.ACTION_UP: break; default: break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; /** * 当滑动时动画操作 */ case MotionEvent.ACTION_MOVE: down_X=interceptTouch_X; down_Y=interceptTouch_Y; move_X=event.getX(); move_Y=event.getY(); down_move_X=Math.abs(down_X-move_X); down_move_Y=Math.abs(down_Y-move_Y); /** * 向下滑动 */ if(move_Y>down_Y&&down_move_Y>moveLength&&getCanAnimation()){ downAnimationConfig(); } /** * 向上滑动 */ if(down_Y>move_Y&&down_move_Y>moveLength&&getCanAnimation()){ upAnimationConfig(); } /** * 运行完上面动画处理后,停止运行动画 */ setCanAnimation(false); break; case MotionEvent.ACTION_UP: break; default: break; } return true; } /** * 是否进行动画处理 * @return true:处理 */ private boolean getCanAnimation(){ return isCanAnimation; } /** * 获取当前视图显示类型 * @return */ private int getType(){ return type; } private void setType(int type){ this.type=type; } /** * 设置是否进行动画处理 * @param canAnimation */ private void setCanAnimation(boolean canAnimation){ this.isCanAnimation=canAnimation; } /** * 向下滑动时的动画处理 */ private void downAnimationConfig(){ switch (getType()) { case HALF://当视图显示一半时 half2None(); break; case ALL://当视图所有显示时 all2Half(); break; default: break; } } /** * 向上滑动时的动画处理 */ private void upAnimationConfig(){ switch (getType()) { case HALF://当视图显示一半时 half2All(); break; case ALL://当视图所有显示时 /** * 当视图已经完整显示,再往 * 上滑动也就没不论什么意义进行 * 动画处理。 */ break; default: break; } } /** * 向下滑动时是否交由onTouch事件处理 * @return true:由onTouch事件处理,不传递给子View */ private boolean isDounTransferOnTouch(){ switch (type) { case NONE: break; case HALF: return true; case ALL: if(isCanHide){ return true; } break; default: break; } return false; } /** * 向上滑动时是否交由onTouch事件处理 * @return true:由onTouch事件处理。不传递给子View */ private boolean isUpTransferOnTouch(){ switch (type) { case NONE: break; case HALF: return true; case ALL: break; default: break; } return false; } /** * 当向下滑动时,当前视图显示一半,再往下滑动隐藏。

* type设置为NONE */ private void half2None(){ float[] values=new float[]{move_height,getHeight()}; startAnimation(values); setType(NONE); } /** * 当向下滑动时。当前视图显示完整,再往下滑动视图显示一半。 * type设置为HALF */ private void all2Half(){ float[] values=new float[]{0,move_height}; startAnimation(values); setType(HALF); } /** * 当向上滑动时,当前视图显示一半,再往上滑动,视图显示完整。 * type设置为ALL */ private void half2All(){ float[] values=new float[]{move_height,0}; startAnimation(values); setType(ALL); } /** * 运行动画 * @param values */ private void startAnimation(float[] values){ AnimatorSet as=new AnimatorSet(); ObjectAnimator anim=ObjectAnimator.ofFloat(this, "translationY", values); anim.setDuration(500); as.playTogether(anim); as.start(); } /** * 当前视图显示完整时的动画处理 */ private void all2None(){ float[] values=new float[]{0,getHeight()}; startAnimation(values); setType(HALF); } /** * 隐藏浮层 */ public void beforeInput(){ switch (getType()) { case NONE: break; case HALF: half2None(); break; case ALL: all2None(); break; default: break; } } /** * 显示浮层一半 */ public void none2Half(){ float[] values=new float[]{getHeight(),move_height}; startAnimation(values); setType(HALF); } /** * 显示所有浮层 */ public void none2All(){ float[] values=new float[]{getHeight(),0}; startAnimation(values); setType(HALF); } /** * 是否进行动画滚动 * @param canHide */ public void setCanHide(boolean canHide){ this.isCanHide=canHide; } }

在代码中已经进行了非常具体的凝视。在代码的最后暴露了几个可调用的方法。能够通过这几个方法实现我们的滑动效

果。

在Activity中的通过GridView的OnScrollListener监听事件进行推断何时进行动画的滚动。何时停止,当然在FloatingLa

yerView能够加上想要加的View。比例如以下面在FloatingLayerView中加入了GirdView:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/white" ><Buttonandroid:id="@+id/btn_show"android:layout_width="fill_parent"android:layout_height="50dp"android:text="显示浮层" /><Buttonandroid:id="@+id/btn_hide"android:layout_width="fill_parent"android:layout_height="50dp"android:layout_below="@id/btn_show"android:text="隐藏浮层" /><!-- 覆盖层 --><com.example.floatinglayeranimtion.FloatingLayerViewandroid:id="@+id/activity_shine_ll_cover"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@+id/btn_hide"android:layout_marginTop="40dp"android:background="@android:color/holo_blue_dark"android:visibility="visible" ><GridViewandroid:id="@+id/activity_shine_gv_all"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:layout_marginTop="5dp"android:horizontalSpacing="4dp"android:listSelector="@null"android:numColumns="4"android:verticalSpacing="4dp" ></GridView></com.example.floatinglayeranimtion.FloatingLayerView></RelativeLayout>

Activity的代码例如以下:

public class MainActivity extends Activity implements OnClickListener {private Button btn_show;private Button btn_hide;private GridView gv_all;private TestAdapter testAdapter = new TestAdapter();// 覆盖层private FloatingLayerView mFloatingLayerView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();addListener();}private void initView() {btn_show = (Button) findViewById(R.id.btn_show);btn_hide = (Button) findViewById(R.id.btn_hide);// 覆盖层mFloatingLayerView = (FloatingLayerView) findViewById(R.id.activity_shine_ll_cover);gv_all = (GridView) findViewById(R.id.activity_shine_gv_all);gv_all.setAdapter(testAdapter);}private void addListener() {btn_show.setOnClickListener(this);btn_hide.setOnClickListener(this);gv_all.setOnScrollListener(scrollListener);}@Overridepublic void onClick(View v) {switch (v.getId()) {// 显示浮层case R.id.btn_show:mFloatingLayerView.none2Half();break;// 隐藏浮层case R.id.btn_hide:mFloatingLayerView.beforeInput();break;}}/** 覆盖层中GridView滑动监听 */private OnScrollListener scrollListener = new OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {if (firstVisibleItem == 0) {mFloatingLayerView.setCanHide(true);} else {mFloatingLayerView.setCanHide(false);}}};// =============測试======================private int[] images = new int[] { R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher,R.drawable.ic_launcher };class TestAdapter extends BaseAdapter {@Overridepublic int getCount() {return images.length;}@Overridepublic Object getItem(int position) {return images[position];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.image, null);ImageView imagView = (ImageView) view.findViewById(R.id.iv_show);imagView.setBackgroundResource(images[position]);return view;}}}

OK,至此滑动的浮层已经实现了,欢迎大家吐槽。

-------------------------------------------------------------------------------------------------------------------------------------------------------

转载请注明出处:http://blog.csdn.net/hai_qing_xu_kong/article/details/47806881情绪控

项目GitHub地址:https://github.com/LinhaiGu/FloatingLayerAnimtion

Android实现浮层的上下滑动(支持内部加入View)相关推荐

  1. Android之Android实现浮层的上下滑动(支持内部添加View)

    前言 我K,今天居然是情人节,对于资深的单身狗来说,简直是个噩耗,今天注定是各种秀恩爱,心塞中.... 话题到此结束,管他什么情人节,今天给大家带来的是一个浮层的上下滑动,浮层滑动时分三种状态:全部显 ...

  2. android 半浮层框架,GitHub - Jodragon/AnyLayer: Android稳定高效的浮层创建管理框架

    AnyLayer Android稳定高效的浮层创建管理框架. 可取代系统自带Dialog/Popup/BottomSheet等弹窗,可实现单Activity架构的Toast提示,可定制任意样式的Gui ...

  3. android列表滑到底部,Android中判断listview是否滑动到顶部和底部的实现方法

    今天实现listview的下拉刷新和上拉加载的时候,遇到了一个问题,*就是说需要根据listview中滑动的位置来进行下拉刷新和上拉加载.* 具体点,只有当我的listview滑动到最顶部的时候,这时 ...

  4. Android透明到白色滑动渐变,Android中Toolbar随着ScrollView滑动透明度渐变效果实现...

    Android中Toolbar随着ScrollView滑动透明度渐变效果实现 一.思路:监听ScrollView的滑动事件 不断的修改Toolbar的透明度 二.注意 1.ScrollView 6.0 ...

  5. android+默认存储,Android 数据存储之SP存储,内部存储,外部存储

    Android 数据存储之SP存储,内部存储,外部存储 Android提供了多种数据存储的技术来永久的保存应用数据,以便于开发者能够根据自己的需求来选择合适的数据存储方案,主要有SharedPrefe ...

  6. android 滑动标签框架,Android实现网易严选标签栏滑动效果

    Android实现网易严选标签栏滑动效果 发布时间:2020-10-13 00:13:46 来源:脚本之家 阅读:85 作者:wlkdb 标签栏是一个非常常见的控件,似乎也是一个比较简单的控件,但如果 ...

  7. 【经验】为什么Android手机连接USB后查看手机内部图片有些有缩略图,有些显示图标?

    [经验]为什么Android手机连接USB后查看手机内部图片有些有缩略图,有些显示图标? 一.图片内嵌缩略图原理 这是什么原理呢?因为现在JPEG的文件采用了压缩的方式,其过程比较复杂.为了能让大家快 ...

  8. Android模仿QQ的左右滑动切换界面和下拉更新的效果

    转自http://www.linuxidc.com/Linux/2012-08/67207.htm 主布局main.xml <?xml version="1.0" encod ...

  9. Android仿小米时钟嵌套滑动(NestedScroll, 自定义behavior)

    最近无聊刷手机的时候, 发现小米时钟的嵌套滑动很有意思, 就试着做了下 先上对比图: 分析下小米时钟的滑动 闹钟列表 向上滑动时, 时钟面 透明度上升, 快到最大滑动时逐渐显示数字时钟. 在闹钟列表向 ...

最新文章

  1. HDU3037(卢卡斯定理)
  2. 005 反转单链表(迭代递归)
  3. 【每日一题】7月15日题目精讲—生日快乐
  4. ThreadLocal线程范围内的共享变量
  5. Java 面向对象 之 静态内部类
  6. MongoDB 聚合管道(Aggregation Pipeline)
  7. c语言程序关键字查询,C语言关键字大全(共32个)
  8. 采用文件白名单方式构建主机安全环境
  9. python制作模型排放清单_四川省人为源大气污染物排放清单及特征
  10. 运放输入偏置电流方向_运算放大器的输入偏置电流
  11. 计算机专业英文授课,计算机专业全英文授课分析
  12. Chrome Edge与Safari书签同步
  13. Diy-Scratch(4) 大家来找茬
  14. Paper翻译:《MobileNet Based Apple Leaf Diseases Identification》
  15. CAD梦想画图中的“阵列命令”
  16. HTTP常见状态码 200 301 302 404 500
  17. 通过路由器连接JetsonNano与地面站
  18. 麒麟系统查看微信聊天记录位置、微信收到的文件位置
  19. web前端需要学习什么?需要掌握什么技术
  20. OpenGL BRDF和IBL渲染

热门文章

  1. Oracle数据库awr报告使用与分析
  2. 为什么要用spring
  3. 测试专员如何编写优秀的测试代码·单元测试篇
  4. 之前项目从未写过的PO2VO
  5. pythondjango是干什么的_python django框架是什么?怎么使用?
  6. 闰年判断_小学数学,平年和闰年怎么判断,百年不闰很多人都容易忘
  7. surface simplification using quadratic error metrics
  8. 老毛桃安装WIN7原版系统
  9. 【java】字符串和基本数据类型之间的转换
  10. 手把手教你搭建pytorch深度学习网络