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