类似Iphone Assistive Touch的控件的实现

  网上也有些这方面的控件,不过貌似不怎么好用,或者是论坛需要积分下载,恰好自己在项目中有用到这种控件,就打算自己写一个,也成功实现了这种功能。今天就打算把这个小控件分享到博客上,供大家参考学习。

  下面贴出控件的代码:

package com.example.com.sus;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.RelativeLayout;
import android.widget.Scroller; /**
* file.test4.WSuspensionButton
*
* <p>as iphone AssistiveTouch</p>
* @author b
* @version 1.0
*
*/
public class WSuspensionButton extends View { private static final int SIZE = 50;
private int size;
private int sizeHalf;
private int stateHeight;
private Scroller mScroller;
private int screenWidth;
private int screenWidthHalf;
private int screenHeight;
private int screenHeightHalf; private int topLine;
private int leftLine;
private int rightLine;
private int bottomLine; public WSuspensionButton(Context context) {
this(context, null);
} public WSuspensionButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} private void init() { recordX = 0;
recordY = 0;
stateHeight = 0;
mScroller = new Scroller(getContext());
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
size = (int)(SIZE * dm.density);
sizeHalf = size / 2;
screenWidth = dm.widthPixels;// 屏幕宽
screenHeight = dm.heightPixels - getStatusBarHeight();
screenWidthHalf = screenWidth / 2;
screenHeightHalf = screenHeight / 2 + stateHeight; // 紧紧只会左右飞
topLine = 0;
bottomLine = screenHeight - topLine;
} /**
* state bar height
* @return
*/
public int getStatusBarHeight() {// 状态栏高度
int result = 0;
int resourceId = getContext().getResources().getIdentifier("status_bar_height",
"dimen", "android");
if (resourceId > 0) {
result = getContext().getResources().getDimensionPixelSize(resourceId);
}
return result;
} public int getSize() {
return size;
} float recordX;
float recordY;
float tempX;
float tempY;
int recordLeft;
int recordTop;
int recordRight;
int recordBottom;
int state;
boolean isMoved;
@SuppressLint("ClickableViewAccessibility")
public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
state = 0;
isMoved = false;
recordX = event.getRawX();
recordY = event.getRawY();
tempX = recordX;
tempY = recordY;
break;
case MotionEvent.ACTION_MOVE:
int intx = (int)(event.getRawX() - tempX);
int inty = (int)(event.getRawY() - tempY);
tempX = event.getRawX();
tempY = event.getRawY();
if(Math.abs(tempX - recordX) < 5 && Math.abs(tempY - recordY) < 5) {
if(state == 0) {
state = 1;
return true;
}
} else {
isMoved = true;
}
if(isMoved && state != 2)
state = 2;
if(state != 2) return true;
int left = getLeft() + intx;
int top = getTop() + inty;
int right = getRight() + intx;
int bottom = getBottom() + inty;
if(left < 0) {
left = 0;
right = getWidth();
}
if(right > screenWidth) {
left = screenWidth - getWidth();
right = screenWidth;
}
if(top < stateHeight) {
top = stateHeight;
bottom = stateHeight + getHeight();
}
if(bottom > screenHeight) {
top = screenHeight - getHeight();
bottom = screenHeight;
}
layout(left, top, right, bottom);
break;
case MotionEvent.ACTION_UP:
if(state != 2) {
if(clickedlistener != null)
clickedlistener.onClick(this);
return true;
}
recordLeft = getLeft();
recordTop = getTop();
recordRight = getRight();
recordBottom = getBottom();
Log.v("AC", "left:"+recordLeft+"\nright:"+recordRight+"\ntop:"+recordTop+"\nbottom:"+recordBottom);
if(getLeft() <= 0 || getTop() <= stateHeight ||
getRight() >= screenWidth || getBottom() >= screenHeight) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)getLayoutParams();
int leftX = getLeft();
int topX = getTop();
params.setMargins(getLeft(), getTop(), 0, 0);
setLayoutParams(params);
if(completeMoveListener != null) completeMoveListener.onCompleteMove(this, leftX, topX);
} else {
// 控件中心y,小于topline,向上飞
// 控件中心y,大于bottomLine,向下飞
// 控件中心x,小于屏幕可视中心x,向左飞
// 控件中心x,大于屏幕可视中心x,向右飞
if((getTop() + sizeHalf) <= topLine) {
scrollToTop();
} else if((getBottom() + sizeHalf) >= bottomLine) {
scrollToBottom();
} else if((getLeft() + sizeHalf) < screenWidthHalf) {
scrollToLeft();
} else {
scrollToRight();
}
}
break;
default:
break;
} return true;
} public void computeScroll() {
if(mScroller.computeScrollOffset()) {
layout(recordLeft + mScroller.getCurrX(),
recordTop + mScroller.getCurrY(),
recordRight + mScroller.getCurrX(),
recordBottom + mScroller.getCurrY());
postInvalidate();
if(mScroller.isFinished()) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)getLayoutParams();
int left = recordLeft + mScroller.getCurrX();
int top = recordTop + mScroller.getCurrY();
params.setMargins(left, top, 0, 0);
setLayoutParams(params);
if(completeMoveListener != null) completeMoveListener.onCompleteMove(this, left, top);
}
} } private void scrollToLeft() {
mScroller.startScroll(0, 0, -recordLeft, 0);
postInvalidate();
} private void scrollToTop() {
mScroller.startScroll(0, 0, 0, -recordTop + stateHeight);
postInvalidate();
} private void scrollToRight() {
mScroller.startScroll(0, 0, screenWidth - recordRight, 0);
postInvalidate();
} private void scrollToBottom() {
mScroller.startScroll(0, 0, 0, screenHeight - recordBottom);
postInvalidate();
} //-------------------
// 监听
//-------------------
private ClickListener clickedlistener;
public void setClickListener(ClickListener clickedlistener) {
this.clickedlistener = clickedlistener;
}
public interface ClickListener {
public void onClick(View v);
} private CompleteMoveListener completeMoveListener;
public void setCompleteMoveListener(CompleteMoveListener completeMoveListener) {
this.completeMoveListener = completeMoveListener;
}
public interface CompleteMoveListener {
public void onCompleteMove(View v, int left, int top);
}
}

  原则上可以向上,向下,向左,向有飞,但实现的时候感觉阉割一下下比较清爽,就只实现了左右飞,判断控件移动方向是根据控件空心位置和限制条件决定的:

private int topLine;
private int bottomLine;
private int leftLine;
private int rightLine

  限制条件是1、topLine=0,2、bottomLine=screenHeight-状态栏高度,3、screenHeight=屏幕高-状态栏高,4、屏幕中心x坐标。

  下面是main.xml布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.com.sus.MainActivity" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" /> <com.example.com.sus.WSuspensionButton
android:id="@+id/btnSus"
android:layout_width="50dp"
android:layout_height="50dp"
/> </RelativeLayout>

  下面是在Activity中的初始化设置:

WSuspensionButton suspensionButton = (WSuspensionButton)findViewById(R.id.btnSus);
int size = suspensionButton.getSize();
suspensionButton.setBackground(new ColorDrawable(Color.BLUE));
RelativeLayout.LayoutParams wmParams = new RelativeLayout.LayoutParams(
size, size);
wmParams.leftMargin = preferences.getInt("suspend_btn_x", dm.widthPixels
- size);
wmParams.topMargin = preferences.getInt("suspend_btn_y",
(dm.heightPixels - size) / 2);
suspensionButton.setLayoutParams(wmParams);// 取本地存入的位置信息,并从新设定控件的坐标
suspensionButton
.setClickListener(new WSuspensionButton.ClickListener() { public void onClick(View v) {
showToast();
} private void showToast() {
Toast.makeText(mActivity,
"You clicked speaker button!",
Toast.LENGTH_SHORT).show();
}
});
suspensionButton
.setCompleteMoveListener(new WSuspensionButton.CompleteMoveListener() { public void onCompleteMove(View v, int left, int top) {
saveInLocal(left, top);
} private void saveInLocal(int left, int top) {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("suspend_btn_x", left);
editor.putInt("suspend_btn_y", top);
editor.commit();
}
});

  在初始化该控件的时候,对该控件的大小以及屏幕中显示的位置进行了从新设置,让其显示在靠屏幕右侧的中心位置。

  好了,以上就是今天的干货。分享愉快

  转载请标明转载地址:http://www.cnblogs.com/swalka/p/5078109.html

Andoird实现类似iphone AssistiveTouch的控件的demo的更多相关文章

  1. iOS iPhone iPad 各种控件默认高度

    iPhone iPad 各种控件默认高度 注意:这些是ios7之前的,ios7之后(包括ios7)有改动,我会在后面标注出来 iPhone和iPad下各种常见控件的宽度和标准是一样的,所以这里就用iP ...

  2. WPF常用控件应用demo

    WPF常用控件应用demo 一.Demo 1.Demo截图如下: 2.demo实现过程 总体布局:因放大缩小窗体,控件很根据空间是否足够改变布局,故用WrapPanel布局. <ScrollVi ...

  3. 如何在web中实现类似excel的表格控件

    Execl功能非常强大,内置的很多函数或公式可以大大提高对数据的加工处理能力.那么在web中有没有类似的控件呢?经过一番搜寻,发现handsontable具备了基本的excel功能支持公式,同时能对数 ...

  4. .NET在WebForm里实现类似WinForm里面TrackBar控件的效果(AJAX Control Toolkit的使用)

    WinForm 里面有一个 TrackBar 控件,表示一个标准的 Windows 跟踪条,是类似于 ScrollBar 控件的可滚动控件.用这个控件可以实现很多可以实时调整的功能,比如最常见的音量调 ...

  5. iPhone iPad 各种控件默认高度

    iPhone和iPad下各种常见控件的宽度和标准是一样的,所以这里就用iPhone说明. 以下是常见的几种控件的高度.Statusbar,Navigationbar和Tabbar的宽度极其图标大小. ...

  6. Android仿IOS的AssistiveTouch的控件EasyTouch实现

    概述: 之前我听到过一则新闻,就是说Ipone中的AssistiveTouch的设计初衷是给残疾人使用的. 而这一功能在亚洲(中国)的使用最为频繁. 虽不知道这新闻的可靠性,但无庸置疑的是它的确给我们 ...

  7. Android类似日历的翻转控件

    最近写了个翻转面板的控件拿出来与大家分享一下,类似日历的那种,写的比较简单有需要的可以直接拿去用.直接上效果图吧,代码我放在百度云了,有问题的话直接回复就好呢,大家一起交流下. http://pan. ...

  8. Delphi 制作自定义数据感知控件并装入包(dpk文件)中(与DBText类似的数据感知控件)

    一.基础知识简介: 1.包的命名介绍: 包的命名没有规则,但是建议遵守包的命名约定:包的命名与包的版本相关,包的名称前面几个字符通常表示作者或公司名,也可以是控件的一个描述词,后面紧跟的Std表示运行 ...

  9. 【WPF】推荐一款拖拉缩放控件的DEMO

    引言 在CodeProject上有个实现了控件拖拉缩放的DEMO,界面很漂亮,里面对Thumb和Adorner运用得很精彩.我觉得,使用WPF的开发者都可以去学习一下.下面放出链接. WPF Diag ...

随机推荐

  1. PHP开发学习门户改版效果图投票

    亲们,PHP开发学习门户上线两个月啦,站长想进行一次改版.希望大家在留下宝贵的一票.选出喜欢的样式吧 A样式: B样式: mod=misc&action=votepoll&fid=46 ...

  2. ADO.NET之1-数据库连接---ShinePans

    ADO.NET技术主要包含Connection,Command,DataReader,DataAdapter,DateSet,DataTable等六种对象 1).Connection 对象的主要功能是 ...

  3. 关于matlab矩阵卷积conv2和傅里叶变换求卷积ifft2的关系

    先定义两个矩阵 a = [1 2 3 5 ; 4 7 9 5;1 4 6 7;5 4 3 7;8 7 5 1] %a矩阵取5*4 b = [1 5 4; 3 6 8; 1 5 7]   %b矩阵如多数 ...

  4. 秒杀多线程第二篇 多线程第一次亲热接触 CreateThread与_beginthreadex本质差别

    本文将带领你与多线程作第一次亲热接触,并深入分析CreateThread与_beginthreadex的本质差别,相信阅读本文后你能轻松的使用多线程并能流畅准确的回答CreateThread与_beg ...

  5. HDU 4940(杭电更多的学校#7 1006) Destroy Transportation system(到处乱混)

    职务地址:pid=4940">HDU 4940 当时这个题一看就看出来了是网络流的最小割.然后就一直在想建图. .然后突然发现,应该要让T集合的数目最少,不然仅仅要有两个,那这两个的每 ...

  6. jersey client上传下载文件

    jersey client上传文件demo File file = new File("/tmp/test.jpg"); System.out.println(file.exist ...

  7. HDU 4790 Just Random 数学

    链接:pid=4790">http://acm.hdu.edu.cn/showproblem.php?pid=4790 意:从[a.b]中随机找出一个数字x,从[c.d]中随机找出一个 ...

  8. 在Java中如何使用jdbc连接Sql2008数据库(转)

    我们在javaEE的开发中,肯定是要用到数据库的,那么在javaEE的开发中,是如何使用代码实现和SQL2008的连接的呢?在这一篇文章中,我将讲解如何最简单的使用jdbc进行SQL2008的数据库的 ...

  9. ecshop中getAll ,getOne ,getRow的区别

    ecshop的数据库抽象层其实就是在模仿adodb $GLOBALS['db']->getAll($sql);//以二维关联数组返回所有数据 $GLOBALS['db']->getOne( ...

  10. cocos2d-x 精灵的创建和基本使用

    在cocos2d-x中.精灵能够说是一个最重要的组成元素,它代表游戏中一个最小的可见单位.同一时候也是CCNode一个最为灵活的子类,由于它能够通过装载一个平面纹理,从而具有丰富的表现力. 在进一步说 ...