Android自定义组件系列【15】——四个方向滑动的菜单实现
今天无意中实现了一个四个方向滑动的菜单,感觉挺好玩,滑动起来很顺手,既然已经做出来了就贴出来让大家也玩弄一下。
一、效果演示
(说明:目前没有安装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自定义组件系列【15】——四个方向滑动的菜单实现的更多相关文章
- Android自定义组件——四个方向滑动的菜单实现
今天无意中实现了一个四个方向滑动的菜单,感觉挺好玩,滑动起来很顺手,既然已经做出来了就贴出来让大家也玩弄一下. 一.效果演示 (说明:目前没有安装Android模拟器,制作的动态图片太卡了,就贴一下静 ...
- Android自定义组件系列【7】——进阶实践(4)
上一篇<Android自定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识,这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpan ...
- Android自定义组件系列【6】——进阶实践(3)
上一篇<Android自定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计划 ...
- Android自定义组件系列【5】——进阶实践(2)
上一篇<Android自定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这一 ...
- Android自定义组件系列【4】——自定义ViewGroup实现双侧滑动
在上一篇文章<Android自定义组件系列[3]--自定义ViewGroup实现侧滑>中实现了仿Facebook和人人网的侧滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布局示 ...
- Android自定义组件系列【3】——自定义ViewGroup实现侧滑
有关自定义ViewGroup的文章已经很多了,我为什么写这篇文章,对于初学者或者对自定义组件比较生疏的朋友虽然可以拿来主义的用了,但是要一步一步的实现和了解其中的过程和原理才能真真脱离别人的代码,举一 ...
- Android自定义组件系列【17】——教你如何高仿微信录音Toast
一.Toast介绍 平时我们在Android开发中会经常用到一个叫Toast的东西,官方解释如下 A toast is a view containing a quick little message ...
- Android自定义组件系列【13】——Android自定义对话框如此简单
在我们的日常项目中很多地方会用到对话框,但是Android系统为我们提供的对话框样子和我们精心设计的界面很不协调,在这种情况下我们想很自由的定义对话框,或者有的时候我们的对话框是一个图片,没有标题和按 ...
- Android自定义组件系列【12】——非UI线程绘图SurfaceView
一.SurfaceView的介绍 在前面我们已经会自定义View,使用canvas绘图,但是View的绘图机制存在一些缺陷. 1.View缺乏双缓冲机制. 2.程序必须重绘整个View上显示的图片,比 ...
随机推荐
- 使用systemctl自定义系统服务
1.创建系统服务文件,格式如下: [Unit] Description=httpd After=network.target [Service] Type=forking ExecStart=/usr ...
- HTTP 文件共享服务器工具 - chfs
CuteHttpFileServer/chfs是一个免费的.HTTP协议的文件共享服务器,使用浏览器可以快速访问.它具有以下特点: 单个文件,整个软件只有一个可执行程序,无配置文件等其他文件 跨平台运 ...
- tomcat怎样禁止显示文件夹和文件列表
查看原文:http://www.ibloger.net/article/300.html Tomcat禁止显示文件夹和文件列表 打开 tomcat的安装文件夹/conf/web.xml 文件 &l ...
- Linux下安装过程中编译PHP时报错:configure: error: libjpeg.(a|so) not found
在Linux下安装PHP过程中,编译时出现configure: error: libjpeg.(a|so) not found 错误的解决的方法: 检查之后发现已经安装libjpeg.可是/usr/l ...
- nodejs 实现简单 http 代理并缓存
var http = require('http'), fs = require("fs"), url = require('url'), querystring = requir ...
- c++命名规范与代码风格
http://blog.sina.com.cn/s/blog_a3a8d0b1010100uw.html http://www.cnblogs.com/len3d/archive/2008/02/01 ...
- php如何实现简繁体互转
php如何实现简繁体互转 一.总结 一句话总结:大部分字是一样的,只转不同的即可 具体转换就是在映射表中找对应的即可 1.简繁体转换的常见问题是什么? 能否智能转换,就是词组, 例如:简体“ 皇后 ” ...
- CURRENMONTH TAG in Automation Framework
/** * @param input * <CURRENTMONTH><CURRENTMONTH+1> * @return Month "MM" */ pr ...
- Python TurtleWorld configuration and simple test
TurtleWorld provides a set of functions for drawing lines by steering turtles around the screen. You ...
- 从C到OCblocks语法的声明
在过去的一段时间,我开始从C的一些简单声明到更复杂的学习直到我开始学习了Objective-C中的blocks.我花了很长的一段时间去理解他并且认识到一旦你理解它是怎样组织的并且是怎样产 ...