zoukankan      html  css  js  c++  java
  • 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+" right:"+recordRight+" top:"+recordTop+" bottom:"+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

  • 相关阅读:
    洛谷1052——过河(DP+状态压缩)
    mod4最优路径问题(转载)
    初次接触python,怎么样系统的自学呢?
    对AM信号FFT的matlab仿真
    初次使用自己写的testbench 验证了简单的NOT门。
    写简单的tb(testbench)文件来测试之前的FSM控制的LED
    利用简单的有限状态机(FSM)来实现一个简单的LED流水灯
    利用状态机(FSM)进行简单的uart串口发送数据
    用matlab脚本语言写M文件函数时用三种方法简单实现实现DFT(离散傅里叶变换)
    作为新手对于初次接触matlab的一些感受。
  • 原文地址:https://www.cnblogs.com/swalka/p/5078109.html
Copyright © 2011-2022 走看看