package com.efrobot.client.remotecontrol.customer;
import android.content.Context;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.efrobot.client.remotecontrol.R;
/**
* Created by guo on 2016/6/8.
* 自定義方向控制,控制機器人的運動方向
* 1.在onTouch事件的時候保存手指點下的位置,保存成兩個point對象,一個是背景的backgroundPoint,一個是軌跡球的point。調用requestLayout重新調用onLayout進行擺放位置
* 2.在onMove事件中
*/
public class RudderView extends ViewGroup {
public final static int MODEL_ALL = 0;
public final static int MODEL_UP_DOWN = 1;
public final static int MODEL_LEFT_RIGHT = 2;
private int viewWidth;
private int viewHeight;
private int model = MODEL_ALL;
private boolean isProcessTouch;
/**
* 軌跡球滑動監聽
*/
private RudderViewListener mRudderViewListener;
/**
* 是否子控件
*/
private boolean isOnLayout = false;
/**
* 背景View
*/
private Point backGroundPoint = new Point();
/**
* 軌跡圓點View
*/
private Point mPoint = new Point();
/**
* 軌跡圓點得活動范圍
*/
private int pointDistance = 0;
/**
* 是否顯示子View
*/
private boolean isShow = true;
/**
* xml中聲明此View,生成View對象時會調用此構造函數
* @param context 上下文
* @param attrs view的屬性
*/
public RudderView(Context context, AttributeSet attrs) {
super(context, attrs);
//初始化背景和軌跡球id
int[] ids ={R.id.tv_point, R.id.tv_bg};
//初始化控件和軌跡球的背景圖片
int[] backGrounds ={R.mipmap.remote_control_point, R.mipmap.remote_control_background};
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
//初始化控件和軌跡球
for(int i = 0; i < ids.length; i++) {
TextView textView = new TextView(context);
textView.setId(ids[i]);
textView.setLayoutParams(params);
textView.setBackgroundResource(backGrounds[i]);
addView(textView);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
viewWidth = getMeasuredWidth();
viewHeight = getMeasuredHeight();
}
public void enableProcessTouch(boolean isProcessTouch) {
this.isProcessTouch = isProcessTouch;
}
/**
* 分布view的位置
* @param view 需要分布的view
* @param mPoint 位置點
*/
private void layoutChildView(View view, Point mPoint) {
int x = 0;
int y = 0;
int measuredWidth = view.getMeasuredWidth();
int measuredHeight = view.getMeasuredHeight();
//計算出 繪制的
int left = mPoint.x - measuredWidth / 2;
int top = mPoint.y - measuredHeight / 2;
int right = mPoint.x + measuredWidth / 2;
int bottom = mPoint.y + measuredHeight / 2;
if(left < 0) {
left = 0;
right = left + measuredWidth;
x = right / 2;
}
if(top < 0) {
top = 0;
bottom = top + measuredHeight;
y = bottom /2;
}
if(right > viewWidth) {
right = viewWidth;
left = viewWidth - measuredWidth;
x = (right + left) /2;
}
if(bottom > viewHeight) {
bottom = viewHeight;
top = bottom - measuredHeight;
y = (bottom + top) /2;
}
view.layout(left, top, right, bottom);
// if(view.getId() == R.id.tv_point) {
//// if(x != 0 && y != 0) {
//// mPoint.set(x, y);
//// }
// }else {
// if(x != 0 && y != 0) {
// mPoint.set(x, y);
// }
// }
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int pointRadius = 0;
int backRadius = 0;
int childCount = getChildCount();
for(int i = 0; i < childCount ; i++) {
View view = getChildAt(i);
if(isOnLayout && isShow) {
if(view.getId() == R.id.tv_point) {
layoutChildView(view, mPoint);
if(pointRadius == 0) {
pointRadius = view.getWidth();
}
}else {
layoutChildView(view, backGroundPoint);
if(backRadius == 0) {
backRadius = view.getWidth();
}
}
}else {
//手離開屏幕或者第一次的時候,不顯示其子View
view.layout(-100,-100,-1,-1);
}
}
if(pointDistance == 0) {
if(pointRadius != 0 && backRadius != 0) {
// pointDistance = (backRadius - pointRadius) /2;
pointDistance = backRadius /2;
}
}
}
public void setModel(int model) {
this.model = model;
}
/**
* 設置軌跡球的監聽
* @param mRudderViewListener 軌跡球的監聽
*/
public void setRudderViewListener(RudderViewListener mRudderViewListener) {
this.mRudderViewListener = mRudderViewListener;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
if(!isOnLayout) isOnLayout = true;
backGroundPoint.set((int) event.getX(), (int) event.getY());
mPoint.set(backGroundPoint.x, backGroundPoint.y);
requestLayout();
break;
case MotionEvent.ACTION_MOVE:
if(!isOnLayout) isOnLayout = true;
calculateInDontMoveBackPoint((int) event.getX(), (int) event.getY());
requestLayout();
break;
case MotionEvent.ACTION_UP:
if(isOnLayout) isOnLayout = false;
requestLayout();
break;
}
notifyListener(event.getAction());
return true;
}
@Override
public void setVisibility(int visibility) {
isShow = visibility != View.GONE;
requestLayout();
}
/**
* 計算背景點和手指移動點的顯示位置(底部背景不動)
*/
private void calculateInDontMoveBackPoint(int x, int y) {
int yDistance = y - backGroundPoint.y;
int xDistance = x - backGroundPoint.x;
int offsetX = Math.abs(xDistance);
int offsetY = Math.abs(yDistance);
if (offsetX * offsetX + offsetY * offsetY > pointDistance * pointDistance) {
if(offsetX == 0) {
mPoint.y = yDistance > 0 ? backGroundPoint.y + pointDistance : backGroundPoint.y - pointDistance;
} else
if(offsetY == 0) {
mPoint.x = xDistance > 0 ? backGroundPoint.x + pointDistance : backGroundPoint.x - pointDistance;
}
else {
float ver = (float)offsetY / (float)offsetX;
double calculateX = Math.sqrt(pointDistance * pointDistance / (ver * ver + 1));
double calculateY = calculateX * ver;
if(x > backGroundPoint.x ) mPoint.x = backGroundPoint.x + (int)calculateX;
else mPoint.x = backGroundPoint.x - (int)calculateX;
if(y > backGroundPoint.y ) mPoint.y = backGroundPoint.y + (int)calculateY;
else mPoint.y = backGroundPoint.y - (int)calculateY;
}
}else {
mPoint.set(x, y);
}
}
/**
* 計算背景點個軌跡球的位置
*/
private void calculateInMoveBackPoint(int x, int y) {
if(model == MODEL_LEFT_RIGHT) {
mPoint.set(x, mPoint.y);
}else if(model == MODEL_UP_DOWN) {
mPoint.set(mPoint.x, y);
}else {
mPoint.set(x, y);
}
int yDistance = mPoint.y - backGroundPoint.y;
int offsetX = Math.abs(mPoint.x - backGroundPoint.x);
int offsetY = Math.abs(yDistance);
if (offsetX * offsetX + offsetY * offsetY > pointDistance * pointDistance) {
if(offsetX == 0) {
backGroundPoint.y = yDistance > 0 ? mPoint.y - pointDistance : mPoint.y + pointDistance;
}else {
float ver = (float)offsetY / (float)offsetX;
double calculateX = Math.sqrt(pointDistance * pointDistance / (ver * ver + 1));
double calculateY = calculateX * ver;
if(calculateX > 1 ) {
if(mPoint.x > backGroundPoint.x ) backGroundPoint.x = mPoint.x - (int)calculateX;
else backGroundPoint.x = mPoint.x + (int)calculateX;
}
if(calculateY > 1) {
if(mPoint.y > backGroundPoint.y ) backGroundPoint.y = mPoint.y - (int)calculateY;
else backGroundPoint.y = mPoint.y + (int)calculateY;
}
}
}
}
/**
* 通知監聽器時軌跡器位置發生了裱花
* @param mAction touch時間的動作(按下,移動,抬起)
*/
private void notifyListener(int mAction) {
if(mRudderViewListener == null) return;
int distanceX = mPoint.x - backGroundPoint.x;
int distanceY = mPoint.y - backGroundPoint.y;
int offsetX = Math.abs(distanceX);
int offsetY = Math.abs(distanceY);
if(pointDistance == 0) return;
int distance = (distanceX * distanceX + distanceY * distanceY) * 100 / (pointDistance * pointDistance);
if(offsetX > offsetY) {
//左右方向
if(distanceX > 0 ) {
//右
mRudderViewListener.onSteeringWheelChanged(this, RudderViewListener.DIRECTION_RIGHT,distance, mAction);
}else if(distanceX < 0) {
//左
mRudderViewListener.onSteeringWheelChanged(this, RudderViewListener.DIRECTION_LEFT,distance , mAction);
}
}else if(offsetX < offsetY) {
//上下方向
if(distanceY > 0 ) {
//下
mRudderViewListener.onSteeringWheelChanged(this, RudderViewListener.DIRECTION_DOWN,distance, mAction);
}else if(distanceY < 0) {
//上
mRudderViewListener.onSteeringWheelChanged(this, RudderViewListener.DIRECTION_UP,distance, mAction);
}
}else if(offsetX == offsetY) {
//斜對角方向
if(distanceX > 0 && distanceY < 0) {
//右上
mRudderViewListener.onSteeringWheelChanged(this, RudderViewListener.DIRECTION_UP_RIGHT,distance, mAction);
}
if(distanceX > 0 && distanceY > 0) {
//右下
mRudderViewListener.onSteeringWheelChanged(this, RudderViewListener.DIRECTION_DOWN_RIGHT,distance, mAction);
}
if(distanceX < 0 && distanceY < 0) {
//左上
mRudderViewListener.onSteeringWheelChanged(this, RudderViewListener.DIRECTION_LEFT_DOWN,distance, mAction);
}
if(distanceX < 0 && distanceY > 0) {
//左下
mRudderViewListener.onSteeringWheelChanged(this, RudderViewListener.DIRECTION_LEFT_UP,distance, mAction);
}
}
}
/**
* 游戲搖桿的位置監聽
*/
public interface RudderViewListener {
int DIRECTION_UP = 0;
int DIRECTION_UP_RIGHT = 1;
int DIRECTION_RIGHT = 2;
int DIRECTION_DOWN_RIGHT = 3;
int DIRECTION_DOWN = 4;
int DIRECTION_LEFT_DOWN = 5;
int DIRECTION_LEFT = 6;
int DIRECTION_LEFT_UP = 7;
/**
* 方向監聽
* @param direction 方向變化
* @param distance 距離變化 最大值為100
*/
void onSteeringWheelChanged(RudderView view, int direction, int distance, int action);
}
}
自定義遙感控件
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
- 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
推薦閱讀更多精彩內容
- 轉載請注明出處:http://blog.csdn.net/linglongxin24/article/detail...
- 在上篇中,我與大家分享了關于如何進行*.lrc歌詞文件的解析,以及將解析完成后的歌詞展示在鑲嵌在ScrollVie...
- 異常情況下Activity的生命周期 內存不足、系統參數改變(比如:屏幕旋轉)、各種國產管家衛士(百度衛士、360...