android自定义view底部可上拉页面
来源:互联网 发布:陕师大网络远程教育 编辑:程序博客网 时间:2024/06/06 00:25
最近有需求,要写一个隐藏在底部,但是支持上下拉的菜单框,于是自己写了一个模型,刚好可以复习一下自定义view、事件分发及属性动画的知识。
废话不多说,先上效果图:
界面很简单,但是有几个难点(大神请略过):
触摸区域处理;
子控件手势拦截;
配合属性动画的使用;
先看一下布局:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="300dp" android:orientation="vertical" android:background="#ffc2c2"> <RelativeLayout android:id="@+id/rl_topbar" android:layout_width="match_parent" android:layout_height="50dp" android:background="#a9a4a4"> <ImageView android:id="@+id/iv_icon" android:layout_width="30dp" android:layout_height="30dp" android:layout_centerVertical="true" android:layout_marginLeft="15dp" android:src="@drawable/arrow_top" /> </RelativeLayout> <LinearLayout android:id="@+id/rl_checkbox" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <CheckBox android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="开关一" android:gravity="center" android:focusable="false"/> <CheckBox android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="开关一" android:gravity="center" android:focusable="false"/> <CheckBox android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="开关一" android:gravity="center" android:focusable="false"/> </LinearLayout></LinearLayout>
一个头部RelativeLayout+3个checkoutbox;
步骤一:定义一个view,我们暂且叫他BottomCard(底部卡片),让他隐藏在布局底部,漏出灰色的头部部分。
//很简单,在构造方法中引入xml布局, public BottomCard(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); View inflate = LayoutInflater.from(context).inflate(R.layout.layout_bottom_card, this, true); }
//在视图发生改变时,也就是在屏幕上显示时,将BottomCard的marginbottom设置为负的(BottomCard的高度-头部的高度(50dp))。 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mBaseMarginBottom = -(getMeasuredHeight() - dipTopx(50)); setRootMarginBottom(getRootLayoutParams(), mBaseMarginBottom); } private void setRootMarginBottom(RelativeLayout.LayoutParams layoutParams, int marginBottom) { layoutParams.bottomMargin = marginBottom; if (layoutParams.bottomMargin >= 0) { layoutParams.bottomMargin = 0; expandStatus = EXPANDED; } else if (layoutParams.bottomMargin <= mBaseMarginBottom) { layoutParams.bottomMargin = mBaseMarginBottom; expandStatus = UNEXPANDED; } layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); setLayoutParams(layoutParams); }
步骤二:让bBttomCard随手势滑入滑出(其实就是根据手势在y轴上的移动而调整BottomMargin的值)。
@Override public boolean onTouchEvent(MotionEvent event) { int distance = 0; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mDownY = event.getRawY(); break; case MotionEvent.ACTION_MOVE: float moveY = event.getRawY(); distance = (int) (moveY - mDownY); moveRootMarginBottom(distance); mDownY = moveY; break; case MotionEvent.ACTION_UP: mDownY = 0; break; } return true; }
这里有一点要注意,获取y轴坐标时一定要用getRawY(),不能用getY(),因为前者是获取手指位置相对于屏幕的y轴坐标,而后者是获取手指位置相对于控件的y坐标,当手指滑出BottomCard的时y的值会不准确。
步骤三:处理子控件的事件分发
这个时候你会发现,BottomCard在拖拽头布局时没问题,但是拖拽BottomCard中头部下面的布局时会无效,这是因为里面的子控件抢了BottomCard的手势事件并且消费,所以不会传给BottomCard来处理,所以我们要对路面的子控件进行处理,只有当手指滑动时,将事件交给BottomCard处理,其他的如点击等由子控件自己来处理。
/** * 如果是滑动事件就将其拦截,交给onTouchEvent处理 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { mDownY = ev.getRawY(); } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { if (Math.abs(ev.getRawY() - mDownY ) > 10) { return true; } } if (super.onInterceptTouchEvent(ev)) { return true; } return false; }
步骤四:当手势拖拽BottomCard向上或者向下滑动时松手,BottomCard会自动执行动画回到顶部或底部。
这里用的是属性动画ValueAnimator,因为ValueAnimator可以毁掉动画执行的整个过程的值,我们可以根据这个值来设置相对应的BottomMargin从而实现动画。
//当手指抬起时 case MotionEvent.ACTION_UP: LayoutParams rootLayoutParams = getRootLayoutParams(); int currentBottomMargin = rootLayoutParams.bottomMargin; if (expandStatus == UNEXPANDED && currentBottomMargin > mBaseMarginBottom) { startExpandAnim(currentBottomMargin); icon.setImageResource(R.drawable.arrow_bottom); } else if (expandStatus == EXPANDED && currentBottomMargin < 0) { startShrinkAnim(currentBottomMargin); icon.setImageResource(R.drawable.arrow_top); } mDownY = 0; break; /** * 开始展开动画 * @param currentBottomMargin 当前的BottomMargin */ private void startExpandAnim(final int currentBottomMargin){ ValueAnimator anim = ValueAnimator.ofInt(currentBottomMargin , 0); anim.setDuration(ANIM_DURATION); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int value = (Integer) animation.getAnimatedValue(); setRootMarginBottom(getRootLayoutParams() , value); } }); anim.start(); } /** * 开始收拢动画 * @param currentBottomMargin 当前的BottomMargin */ private void startShrinkAnim(final int currentBottomMargin){ ValueAnimator anim = ValueAnimator.ofInt(currentBottomMargin , mBaseMarginBottom); anim.setDuration(ANIM_DURATION); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int value = (Integer) animation.getAnimatedValue(); setRootMarginBottom(getRootLayoutParams() , value); } }); anim.start(); }
好的,其实这样就实现了整个功能,看似很简单,但是里面还是有很多知识点可以去学习的!
代码地址点这里!
0 0
- android自定义view底部可上拉页面
- Android自定义View底部连续圆环效果
- Android底部弹出的View,可自定义布局
- Android底部弹出的View,可自定义布局
- 底部导航栏(自定义View+ViewPager实现) android项目详解
- [转]Android底部弹出的View,可自定义布局
- android仿微信底部导航栏+viewPager+自定义view
- Android 自定义view及其属性。友情链接底部有动画链接
- android 使用TabLayout 自定义View布局作为底部菜单栏
- Android自定义view+程序启动引导页面
- Android自定义View之实现流行的底部菜单栏中间突起:高仿“咸鱼APP”的底部菜单。
- Android View---自定义View
- Android View---自定义View
- android linearlayout 把控件view置底部(放在页面最下方)
- Android实现从底部弹出页面以及显示与隐藏显示部分View
- Android高手进阶篇3-自定义ListView实现底部View自动隐藏和消失的功能
- Android高手进阶篇3-自定义ListView实现底部View自动隐藏和消失的功能
- Android自定义View之Activity页面的组成
- 误差、欠拟合和过拟合
- 剑指offer(C++)——旋转数组的最小数字
- struts2总结
- Lintcode32 Minimum Window Substring solution 题解
- NANDflash
- android自定义view底部可上拉页面
- 第2章 软件工程与需求工程
- Android客户端代码保护技术-完整性校验
- 函数指针及函数指针数组
- 1210: OY问题 [搜索]
- hiho1515分数调查
- java_入门基础学习(四)
- KNN算法调用包
- 有一行电文,已按下面规律译成密码:简单译码问题