类似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. c++重载ostream的实现

    #include <iostream> using namespace std; class Point{ public: Point(int _x = 0, int _y = 0, in ...

  2. PV(访问量)、UV(独立访客)、IP(独立IP) (转)

    网站统计中的PV(访问量):UV(独立访客):IP(独立IP)的定义与区别今天使用了雅虎统计,看到里面就有这个,就说说,其实里面的uv大家可能觉得很新奇,但是和站长统计里的独立访客是一样的嘛.---- ...

  3. OpenCV-Python教程(9、使用霍夫变换检测直线)

    相比C++而言,Python适合做原型.本系列的文章介绍如何在Python中用OpenCV图形库,以及与C++调用相应OpenCV函数的不同之处.这篇文章介绍在Python中使用OpenCV的霍夫变换 ...

  4. 如何解决This system is not registered with RHN.

    今天我必须写下这篇文章,由于在我刚刚接触到Linux下安装oracle时碰到了Linux中少xscreensaver.rpm包自己弄了非常久.最后还是被一个大哥帮我攻克了:仅仅能说非常的感谢你! 我试 ...

  5. 一次失败的刷题经历:[LeetCode]292之尼姆游戏(Nim Game)(转)

    最近闲来无事刷LeetCode,发现这道题的Accept Rate还是挺高的,尝试着做了一下,结果悲剧了,把过程写下来,希望能长点记性.该题的描述翻译成中文如下: 你正在和你的朋友玩尼姆游戏(Nim ...

  6. 用Java写个ftp传输类实现文件的上传和下载,用ikvmc转成dll

    1.Java类: package com.wjy.ftp.transmission; import java.io.File; import java.io.FileOutputStream; imp ...

  7. PHP 文件操作类(创建文件并写入) 生成日志

    <?php /** * 文件操作(生成日志)支持多条插入 * (假设插入多条语句并换行 用','逗号分开) * */ class log { public $path = './info.txt ...

  8. Android 一些错误

    android fragment里面放viewpager 嵌套fragment 报错: 解决:在adapter的构造方法里加上 super(fragment.getChildFragmentManag ...

  9. 《JavaScript设计模式与开发实践》读书笔记之策略模式

    1.策略模式 定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换 1.1 传统实现 根据工资基数和年底绩效来发送年终奖 var calculateBonus= function (perfo ...

  10. Lucene 实例教程(四)之检索方法总结

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本人声明.否则将追究法律责任. 作者: 永恒の_☆ 地址: http://blog.csdn.net/chenghui031 ...