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

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

posted @ 2015-12-26 14:52  swalka`x  阅读(443)  评论(0编辑  收藏  举报