Android实现浮层的上下滑动(支持内部加入View)
前言
我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)相关推荐
- Android之Android实现浮层的上下滑动(支持内部添加View)
前言 我K,今天居然是情人节,对于资深的单身狗来说,简直是个噩耗,今天注定是各种秀恩爱,心塞中.... 话题到此结束,管他什么情人节,今天给大家带来的是一个浮层的上下滑动,浮层滑动时分三种状态:全部显 ...
- android 半浮层框架,GitHub - Jodragon/AnyLayer: Android稳定高效的浮层创建管理框架
AnyLayer Android稳定高效的浮层创建管理框架. 可取代系统自带Dialog/Popup/BottomSheet等弹窗,可实现单Activity架构的Toast提示,可定制任意样式的Gui ...
- android列表滑到底部,Android中判断listview是否滑动到顶部和底部的实现方法
今天实现listview的下拉刷新和上拉加载的时候,遇到了一个问题,*就是说需要根据listview中滑动的位置来进行下拉刷新和上拉加载.* 具体点,只有当我的listview滑动到最顶部的时候,这时 ...
- Android透明到白色滑动渐变,Android中Toolbar随着ScrollView滑动透明度渐变效果实现...
Android中Toolbar随着ScrollView滑动透明度渐变效果实现 一.思路:监听ScrollView的滑动事件 不断的修改Toolbar的透明度 二.注意 1.ScrollView 6.0 ...
- android+默认存储,Android 数据存储之SP存储,内部存储,外部存储
Android 数据存储之SP存储,内部存储,外部存储 Android提供了多种数据存储的技术来永久的保存应用数据,以便于开发者能够根据自己的需求来选择合适的数据存储方案,主要有SharedPrefe ...
- android 滑动标签框架,Android实现网易严选标签栏滑动效果
Android实现网易严选标签栏滑动效果 发布时间:2020-10-13 00:13:46 来源:脚本之家 阅读:85 作者:wlkdb 标签栏是一个非常常见的控件,似乎也是一个比较简单的控件,但如果 ...
- 【经验】为什么Android手机连接USB后查看手机内部图片有些有缩略图,有些显示图标?
[经验]为什么Android手机连接USB后查看手机内部图片有些有缩略图,有些显示图标? 一.图片内嵌缩略图原理 这是什么原理呢?因为现在JPEG的文件采用了压缩的方式,其过程比较复杂.为了能让大家快 ...
- Android模仿QQ的左右滑动切换界面和下拉更新的效果
转自http://www.linuxidc.com/Linux/2012-08/67207.htm 主布局main.xml <?xml version="1.0" encod ...
- Android仿小米时钟嵌套滑动(NestedScroll, 自定义behavior)
最近无聊刷手机的时候, 发现小米时钟的嵌套滑动很有意思, 就试着做了下 先上对比图: 分析下小米时钟的滑动 闹钟列表 向上滑动时, 时钟面 透明度上升, 快到最大滑动时逐渐显示数字时钟. 在闹钟列表向 ...
最新文章
- HDU3037(卢卡斯定理)
- 005 反转单链表(迭代递归)
- 【每日一题】7月15日题目精讲—生日快乐
- ThreadLocal线程范围内的共享变量
- Java 面向对象 之 静态内部类
- MongoDB 聚合管道(Aggregation Pipeline)
- c语言程序关键字查询,C语言关键字大全(共32个)
- 采用文件白名单方式构建主机安全环境
- python制作模型排放清单_四川省人为源大气污染物排放清单及特征
- 运放输入偏置电流方向_运算放大器的输入偏置电流
- 计算机专业英文授课,计算机专业全英文授课分析
- Chrome Edge与Safari书签同步
- Diy-Scratch(4) 大家来找茬
- Paper翻译:《MobileNet Based Apple Leaf Diseases Identification》
- CAD梦想画图中的“阵列命令”
- HTTP常见状态码 200 301 302 404 500
- 通过路由器连接JetsonNano与地面站
- 麒麟系统查看微信聊天记录位置、微信收到的文件位置
- web前端需要学习什么?需要掌握什么技术
- OpenGL BRDF和IBL渲染