Andoird实现类似iphone AssistiveTouch的控件的demo

时间:2022-08-17 00:22:56

类似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