Android自定义组件——四个方向滑动的菜单实现
今天无意中实现了一个四个方向滑动的菜单,感觉挺好玩,滑动起来很顺手,既然已经做出来了就贴出来让大家也玩弄一下。
一、效果演示
(说明:目前没有安装Android模拟器,制作的动态图片太卡了,就贴一下静态图片吧,实际效果可以下载源代码查看)
(向上滑动)
(向下滑动)
(向左滑动)
(向右滑动)
二、实现过程介绍
1、放置5个View (分别是上下左右中)
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- mTopView.layout(0, -mViewHeight, mViewWidth, 0);
- mBottomView.layout(0, mViewHeight, mViewWidth, 2 * mViewHeight);
- mCenterView.layout(0, 0, mViewWidth, mViewHeight);
- mLeftView.layout(-mViewWidth, 0, 0, mViewHeight);
- mRightView.layout(mViewWidth, 0, 2 * mViewWidth, mViewHeight);
- }
转载请说明出处:http://blog.csdn.net/dawanganban
2、通过onTouchEvent事件来判断移动方向
- private float mDownY;
- private float mDownX;
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int disY;
- int disX;
- float eventY = event.getY();
- float eventX = event.getX();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mDownY = eventY;
- mDownX = eventX;
- break;
- case MotionEvent.ACTION_UP:
- disY = (int)(eventY - mDownY);
- disX = (int)(eventX - mDownX);
- if(Math.abs(disY) > Math.abs(disX)){
- if(Math.abs(disY) > MIN_VIEW_HEIGHT / 2){
- if(disY > 0){ //向下滑动
- Log.d(TAG, "TO_BOTTOM");
- changeToBottom();
- }else{ //向上滑动
- Log.d(TAG, "TO_TOP");
- changeToTop();
- }
- }
- }else{
- if(Math.abs(disX) > MIN_VIEW_WIDTH / 2){
- if(disX > 0){ //向右滑动
- Log.d(TAG, "TO_RIGHT");
- changeToRight();
- }else{ //向左滑动
- Log.d(TAG, "TO_LEFT");
- changeToLeft();
- }
- }
- }
- break;
- default:
- break;
- }
- return true;
- }
3、通过computerScroll()方法实现平滑移动
- @Override
- public void computeScroll() {
- super.computeScroll();
- if(mScroller.computeScrollOffset()){
- scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
- postInvalidate();
- }
- }
4、判断临界条件(否则会一直向一个方向滑动)
- int[] location = new int[2];
- mCenterView.getLocationOnScreen(location);
- if(location[1] >= mViewHeight - MIN_VIEW_HEIGHT * 2) return;
例如上面代码就是判断向下滑动的临界条件,location[1]代表中间View的y坐标(相对于屏幕)。
三、整个View的源码
- package com.example.testmx4update;
- import android.content.Context;
- import android.graphics.Color;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.Scroller;
- /**
- * 自定义可以拖动的View
- * @author 阳光小强 http://blog.csdn.net/dawanganban
- *
- */
- public class MyCanPullView extends ViewGroup{
- private static final int MIN_VIEW_HEIGHT = 200;
- private static final int MIN_VIEW_WIDTH = 400;
- private static final String TAG = "TEST";
- private int mViewHeight;
- private int mViewWidth;
- private View mTopView;
- private View mBottomView;
- private View mCenterView;
- private View mLeftView;
- private View mRightView;
- private Scroller mScroller;
- public MyCanPullView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initView(context);
- mScroller = new Scroller(context);
- }
- private void initView(Context context) {
- setTopView(context);
- setBottomView(context);
- setCenterView(context);
- setLeftView(context);
- setRightView(context);
- }
- private float mDownY;
- private float mDownX;
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int disY;
- int disX;
- float eventY = event.getY();
- float eventX = event.getX();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mDownY = eventY;
- mDownX = eventX;
- break;
- case MotionEvent.ACTION_UP:
- disY = (int)(eventY - mDownY);
- disX = (int)(eventX - mDownX);
- if(Math.abs(disY) > Math.abs(disX)){
- if(Math.abs(disY) > MIN_VIEW_HEIGHT / 2){
- if(disY > 0){ //向下滑动
- Log.d(TAG, "TO_BOTTOM");
- changeToBottom();
- }else{ //向上滑动
- Log.d(TAG, "TO_TOP");
- changeToTop();
- }
- }
- }else{
- if(Math.abs(disX) > MIN_VIEW_WIDTH / 2){
- if(disX > 0){ //向右滑动
- Log.d(TAG, "TO_RIGHT");
- changeToRight();
- }else{ //向左滑动
- Log.d(TAG, "TO_LEFT");
- changeToLeft();
- }
- }
- }
- break;
- default:
- break;
- }
- return true;
- }
- private void changeToBottom(){
- int[] location = new int[2];
- mCenterView.getLocationOnScreen(location);
- if(location[1] >= mViewHeight - MIN_VIEW_HEIGHT * 2) return;
- int dy = (int)(mViewHeight - MIN_VIEW_HEIGHT);
- mScroller.startScroll(0, getScrollY(), 0, -dy, 500);
- invalidate();
- }
- private void changeToTop(){
- int[] location = new int[2];
- mTopView.getLocationOnScreen(location);
- if(location[1] <= -mViewHeight - MIN_VIEW_HEIGHT / 2) return;
- int dy = (int)(mViewHeight - MIN_VIEW_HEIGHT);
- mScroller.startScroll(0, getScrollY(), 0, dy, 500);
- invalidate();
- }
- private void changeToRight(){
- int[] location = new int[2];
- mCenterView.getLocationOnScreen(location);
- if(location[0] >= mViewWidth - MIN_VIEW_WIDTH * 2) return;
- int dx = (int)(mViewWidth - MIN_VIEW_WIDTH);
- mScroller.startScroll(getScrollX(), 0, -dx, 0, 500);
- invalidate();
- }
- private void changeToLeft(){
- Log.d(TAG, "TO_LEFT");
- int[] location = new int[2];
- mLeftView.getLocationOnScreen(location);
- if(location[0] <= -mViewWidth - MIN_VIEW_WIDTH / 2) return;
- int dx = (int)(mViewWidth - MIN_VIEW_WIDTH);
- mScroller.startScroll(getScrollX(), 0, dx, 0, 500);
- invalidate();
- }
- @Override
- public void computeScroll() {
- super.computeScroll();
- if(mScroller.computeScrollOffset()){
- scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
- postInvalidate();
- }
- }
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- mTopView.layout(0, -mViewHeight, mViewWidth, 0);
- mBottomView.layout(0, mViewHeight, mViewWidth, 2 * mViewHeight);
- mCenterView.layout(0, 0, mViewWidth, mViewHeight);
- mLeftView.layout(-mViewWidth, 0, 0, mViewHeight);
- mRightView.layout(mViewWidth, 0, 2 * mViewWidth, mViewHeight);
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- //获取整个View的宽高
- mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
- mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
- }
- private void setTopView(Context context){
- View topButton = new View(context);
- topButton.setBackgroundColor(Color.RED);
- mTopView = topButton;
- this.addView(mTopView);
- }
- private void setBottomView(Context context){
- View bottomButton = new View(context);
- bottomButton.setBackgroundColor(Color.GREEN);
- mBottomView = bottomButton;
- this.addView(mBottomView);
- }
- private void setCenterView(Context context){
- View centerButton = new View(context);
- centerButton.setBackgroundColor(Color.WHITE);
- mCenterView = centerButton;
- this.addView(mCenterView);
- }
- private void setLeftView(Context context){
- View leftButton = new View(context);
- leftButton.setBackgroundColor(Color.BLUE);
- mLeftView = leftButton;
- this.addView(mLeftView);
- }
- private void setRightView(Context context){
- View rightButton = new View(context);
- rightButton.setBackgroundColor(Color.YELLOW);
- mRightView = rightButton;
- this.addView(mRightView);
- }
- }
获取全部源代码,请加群在群共享中获取(142979499)
Android自定义组件——四个方向滑动的菜单实现的更多相关文章
- Android自定义组件系列【15】——四个方向滑动的菜单实现
今天无意中实现了一个四个方向滑动的菜单,感觉挺好玩,滑动起来很顺手,既然已经做出来了就贴出来让大家也玩弄一下. 一.效果演示 (说明:目前没有安装Android模拟器,制作的动态图片太卡了,就贴一下静 ...
- Android自定义组件系列【4】——自定义ViewGroup实现双侧滑动
在上一篇文章<Android自定义组件系列[3]--自定义ViewGroup实现侧滑>中实现了仿Facebook和人人网的侧滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布局示 ...
- Android自定义组件系列【7】——进阶实践(4)
上一篇<Android自定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识,这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpan ...
- Android自定义视图四:定制onMeasure强制显示为方形
这个系列是老外写的,干货!翻译出来一起学习.如有不妥,不吝赐教! Android自定义视图一:扩展现有的视图,添加新的XML属性 Android自定义视图二:如何绘制内容 Android自定义视图三: ...
- Android自定义组件之自动换行及宽度自适应View:WordWrapView
目的: 自定义一个ViewGroup,里面的子view都是TextView,每个子view TextView的宽度随内容自适应且每行的子View的个数自适应,并可以自动换行 一:效果图 二:代码 整 ...
- Android自定义组件系列【5】——进阶实践(2)
上一篇<Android自定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这一 ...
- Android自定义组件系列【6】——进阶实践(3)
上一篇<Android自定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计划 ...
- Android自定义组件系列【3】——自定义ViewGroup实现侧滑
有关自定义ViewGroup的文章已经很多了,我为什么写这篇文章,对于初学者或者对自定义组件比较生疏的朋友虽然可以拿来主义的用了,但是要一步一步的实现和了解其中的过程和原理才能真真脱离别人的代码,举一 ...
- Android 自定义组件之如何实现自定义组件
参考链接:http://blog.csdn.net/jjwwmlp456/article/details/41076699 简介 Android提供了用于构建UI的强大的组件模型.两个基类:View和 ...
随机推荐
- mybatis 参数为String,用_parameter 取值
mybatis 参数为String,if test读取该参数代码: <select id="getMaxDepartId" parameterType="java. ...
- TensorFlow-GPU:查看电脑显卡型号是否支持CUDN,以及相关软件下载与介绍
1.显卡(GPU)是否支持CUDN https://developer.nvidia.com/cuda-gpus 2.了解基础知识 1)CUDA(Compute Unified Device Arch ...
- RTC教程
Tutorial: Get started with Rational Team Concert Getting Started with Jazz Source Control RTC入门教程及冲突 ...
- jsp连接mysql----------第一篇技术类文章
今天做作业连了一天的mysql. 最后我痛定思痛,决定从0開始学习jsp.省的又面临不会的局面. 忙活了一晚上.最终把数据库连接上了,只是.好伤心啊,我连个数据库都这么墨迹. . . <%@ p ...
- OpenGL核心技术之帧缓冲
笔者介绍:姜雪伟.IT公司技术合伙人,IT高级讲师.CSDN社区专家.特邀编辑.畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...
- GCT之数学公式(几何部分)
一.平面图形 二.空间几何体
- 【WP8】自定义控件
1.测量和安排布局:MeasureOverride, ArrangeOverride //测量(传入控件的可用大小) protected override Size MeasureOverride(S ...
- Postman测试api@RequestBody接收参数
api postman 结果 { , "message": "Content type 'multipart/form-data;boundary=----------- ...
- java使用jdom生成xml格式文件
本文生成xml使用的工具是jdom.jar,下载地址如下: 链接:https://eyun.baidu.com/s/3slyHgnj 密码:0TXF 生成之后的文档格式类型,就如上面的图片一样,简单吧 ...
- Nginx以服务方式启动并用定时任务每天备份日志
1.安装Nginx以服务方式启动: a.下载 instsrv.exe.srvany.exe 以管理员方式启动CMD执行以下命令: instsrv Nginx D:\nginx\srvany.exe b ...