android自定义实现抽屉SlidingDrawer的功能
最近项目中需要实现上拉功能,首先想到的就是Android本身自带的抽屉SlidingDrawer,最后也实现了不过,出现的问题就是设置背景色问题,handler和content是两个不同的部分,这就造成图片要做成两部分,从而产生两个部分图片看起来不是一个整体,而且我这个上拉功能,里面要实现一个水平滚动功能,而SlidingDrawer还有其他的限制,同时官方给出api 17以后,这个功能已经废弃,所以自己自定这样一个上拉功能是必须的。
这里我是继承LinearLayout同时实现GestureDetector.OnGestureListener来实现上拉功能。下面是代码:
package com.example.test; import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.RelativeLayout; public class PanelBom extends LinearLayout implements GestureDetector.OnGestureListener{ GestureDetector mGesture = null;
private boolean isScrolling = false;
private int MAX_HEIGHT = 80;//拖动的最大高度,当前布局位于父布局下面-80位置,这个仅仅是调试参数,这个变量是动态设置的。
private float mScrollX; // 滑块滑动距离
public PanelBom(Context context) {
super(context);
init();
}
public PanelBom(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//初始化一些参数
public void init(){
mGesture = new GestureDetector(this);
mGesture.setIsLongpressEnabled(false);
setBackgroundResource(R.drawable.button_bar);
} @Override
public boolean onTouchEvent(MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction() && isScrolling == true) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)getLayoutParams();
// 缩回去
if (layoutParams.bottomMargin < -MAX_HEIGHT / 2) {
new AsynMove().execute(-20);//负--往下
} else {
new AsynMove().execute(20);//正--往上
}
}
return mGesture.onTouchEvent(event);
}
//Touch down时触发
@Override
public boolean onDown(MotionEvent e) {
mScrollX = 0;
isScrolling = false;
// 将之改为true,不然事件不会向下传递.
return true;
}
//Touch了还没有滑动时触发
@Override
public void onShowPress(MotionEvent e) { }
@Override
public boolean onSingleTapUp(MotionEvent e) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
// 说明在上面,要往下
if (layoutParams.bottomMargin >= 0) {
new AsynMove().execute(-20);//负--往下
} else {
new AsynMove().execute(20);//正--往上
}
return true;
}
//Touch了滑动时触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
isScrolling = true;
mScrollX += distanceY;
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)getLayoutParams();
layoutParams.bottomMargin += mScrollX;
if (layoutParams.bottomMargin >= 0) {
isScrolling = false;// 拖过头了不需要再执行AsynMove了
layoutParams.bottomMargin = 0;
} else if (layoutParams.bottomMargin <= -MAX_HEIGHT) {
// 拖过头了不需要再执行AsynMove了
isScrolling = false;
layoutParams.bottomMargin = -MAX_HEIGHT;
}
setLayoutParams(layoutParams);
return false;
}
//Touch了不移动一直Touch down时触发
@Override
public void onLongPress(MotionEvent e) { }
//Touch了滑动一点距离后,up时触发。
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
//异步更新布局的位置
class AsynMove extends AsyncTask<Integer, Integer, Void> {
@Override
protected Void doInBackground(Integer... params) {
int times = 0;
int divi = Math.abs(params[0]);
if (MAX_HEIGHT % divi == 0)// 整除
times = MAX_HEIGHT / Math.abs(params[0]);
else
times = MAX_HEIGHT / divi + 1;// 有余数 for (int i = 0; i < times; i++) {
publishProgress(params[0]);
try {
Thread.sleep(divi);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
if (values[0] < 0) {
layoutParams.bottomMargin = Math.max(layoutParams.bottomMargin + values[0], -MAX_HEIGHT);
} else {
layoutParams.bottomMargin = Math.min(layoutParams.bottomMargin + values[0], 0);
}
setLayoutParams(layoutParams); super.onProgressUpdate(values);
}
}
}
主界面:
package com.example.test; import android.app.Activity;
import android.os.Bundle;
import android.widget.RelativeLayout; public class Main5 extends Activity{ RelativeLayout Parent;
PanelBom panelBom;
RelativeLayout.LayoutParams parentParams;
RelativeLayout.LayoutParams paneBomParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Parent = new RelativeLayout(getApplicationContext());
panelBom = new PanelBom(getApplicationContext());
parentParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
paneBomParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 150);
paneBomParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
paneBomParams.bottomMargin = -80;
Parent.addView(panelBom, paneBomParams);
setContentView(Parent, parentParams);
} }
实现的效果是:
拖拉,点击实现上拉功能,效果图如下:
android自定义实现抽屉SlidingDrawer的功能的更多相关文章
- Android -- 滑式抽屉SlidingDrawer(非原创)
SlidingDrawer(滑动式抽屉)隐藏屏外的内容,并允许用户拖拽一个handle以显示隐藏的内容.SlidingDrawer可以在垂直或者水平使用.它由两个子视图组成:一个是用户拖拽的handl ...
- android 自定义view之选座功能
效果图: 界面比较粗糙,主要看原理. 这个界面主要包括以下几部分 1.座位 2.左边的排数 3.左上方的缩略图 4.缩略图中的红色区域 5.手指移动时跟随移动 6.两个手指缩放时跟随缩放 主要技术点 ...
- Android控件之SlidingDrawer(滑动式抽屉)详解与实例
SlidingDrawer效果想必大家也见到过,它就是1.5模拟器上进入应用程序列表的效果.下面是截图 一.简介 SlidingDrawer隐藏屏外的内容,并允许用户通过handle以显示隐藏内容.它 ...
- Android抽屉(SlidingDrawer --类似android通知栏下拉效果)
Android抽屉(SlidingDrawer)的实现发 - 红黑联盟http://www.2cto.com/kf/201301/182507.html 可动态布局的Android抽屉之基础http: ...
- (转)[原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- [原] Android 自定义View步骤
例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...
- [原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android 自定义title 之Action Bar
Android 自定义title 之Action Bar 2014-06-29 飞鹰飞龙... 摘自 博客园 阅 10519 转 25 转藏到我的图书馆 微信分享: Action Ba ...
随机推荐
- Reverse Words in a String | LeetCode OJ | C++
我的思路:先读取每一个单词,存放到容器中:读取完毕后,将容器中的单词倒序写入输出中. #include<iostream> #include<string> #include& ...
- html5新特性:利用history的pushState等方法来解决使用ajax导致页面后退和前进的问题
一.背景 使用ajax,可以实现不需要刷新整个页面就可以进行局部页面的更新.这样可以开发交互性很强的富客户端程序,减少网络传输的内容.但长期以来存在一个问题,就是无法利用浏览器本身提供的前进和后退按钮 ...
- Android学习笔记:ActionBar使用介绍
一.基本概念 最权威和官方的介绍请看google的api文档 http://developer.android.com/training/basics/actionbar/setting-up.htm ...
- 动态网页爬取例子(WebCollector+selenium+phantomjs)
目标:动态网页爬取 说明:这里的动态网页指几种可能:1)需要用户交互,如常见的登录操作:2)网页通过JS / AJAX动态生成,如一个html里有<div id="test" ...
- C语言的system函数
这个是与操作系统有关的函数,在linux/unix下system可以运行所有的shell命令windows下system可运行所有的windows执行文件,除DOS命令外,也可运行windwos ...
- ASP.NET中操作SQL数据库
在WebConfig中配置数据库连接字符串,代码如下: <connectionStrings> <add name="ConnectionString&qu ...
- J2EE基础篇——十三个规范
背景: 1.企业级应用框架的需求,在很多企业级应用中.比如数据库连接.邮件服务.事务处理等都是一些通用企业需求模块,这些模块假设每次在开发中都由开发者来完毕的话,将会造成开发周期长和代码可靠性差等问题 ...
- PHP - Windows安装Pear
1. 打开命令窗口,切换到php的安装目录,执行以下命令(你也可以添加一个php的环境变量,就不用如此麻烦的切换目录,但是我安装了多个版本的php,所以就没有添加环境变量). 2. 当出现下面这句话时 ...
- 通过demo搞懂encode_utf8和decode_utf8
perl 编码问题: use utf8表示代码使用UTF-8写的 [root@wx03 0710]# cat a1.pl #use utf8; my $str='测试utf8字符集'; print $ ...
- iOS 获取当前时间以及计算年龄(时间差)
获取当前时间 NSDate *now = [NSDate date]; NSLog(@"now date is: %@", now); NSCalendar *calendar = ...