之前在项目里面绘制摇杆圆盘使用SurfaceView来实现,同时设置SurfaceView透明,但是这样会造成SurfaceView的组件会覆盖其他的组件,一般情况没有关系,而不一般的情况就是有类似上拉和下拉功能,需要拉出的布局位于最顶部,覆盖其他的组件,而由于之前设置SurfaceView透明使用是:

setZOrderOnTop(true);
mHolder.setFormat(PixelFormat.TRANSPARENT);//设置背景透明

这样会使SurfaceView位于布局的最顶部,即使你设置了bringToTop也没有用,解决这类问题有两种方案:

第一种:使用PopupWindow或者类似浮动小窗体的功能,我测试过他们不会被SurfaceView覆盖,但是这种方案只适用于点击实现组件的弹出,不能实现上拉拖动来显示组建(这里的上拉布局是指有一部分在可见窗体之外),不幸的是项目里面需求指定要上拉,而不是点击来实现组件的弹出功能,所以这种方案不适用于我的情况。所以我就找到了第二种情况。

第二种:

自己写一个类来继承View,然后利用onTouchEvent和OnDraw这两个方法来实现绘制图像,具体的见代码:

Jockey_Left类:继承View

package com.example.test;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View; public class Jockey_Left extends View{ private Bitmap bitmap;
public Point mRockerPosition;
public Point mCtrlPoint;
private int mRudderRadius = 25;
public int mWheelRadius = 80;
private float scale;
public int isHide = 0;
private Paint mPaint;
public Jockey_Left(Context context) {
super(context);
} public Jockey_Left(Context context, AttributeSet attrs) {
super(context, attrs);
} public void init(float scale){
this.scale = scale;
mRudderRadius = dip2px(15);
mWheelRadius = dip2px(45);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.print2);
bitmap = Bitmap.createScaledBitmap(bitmap, mRudderRadius*2, mRudderRadius*2, false);
mCtrlPoint = new Point((mRudderRadius + mWheelRadius), (mRudderRadius + mWheelRadius));
mPaint = new Paint();
mPaint.setAntiAlias(true);
mRockerPosition = new Point(mCtrlPoint);
}
public int dip2px(float dpValue) {
return (int)(dpValue * scale + 0.5f);
}
public Canvas canvas;
@Override
protected void onDraw(Canvas canvas) {
if (bitmap != null) {
//canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);//�����Ļ
this.canvas = canvas;
canvas.drawBitmap(bitmap, mRockerPosition.x - mRudderRadius, mRockerPosition.y - mRudderRadius, mPaint);
}
super.onDraw(canvas);
} int len;
@Override
public boolean onTouchEvent(MotionEvent event) {
try {
if (isHide == 0) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
len = MathUtils.getLength(mCtrlPoint.x, mCtrlPoint.y, event.getX(), event.getY());
//如果屏幕接触点不在摇杆挥动范围内,则不处理
if(len > mWheelRadius) {
return true;
}
break;
case MotionEvent.ACTION_MOVE:
len = MathUtils.getLength(mCtrlPoint.x, mCtrlPoint.y, event.getX(), event.getY());
if(len <= mWheelRadius) {
//如果手指在摇杆活动范围内,则摇杆处于手指触摸位置
mRockerPosition.set((int)event.getX(), (int)event.getY());
}else{
//设置摇杆位置,使其处于手指触摸方向的 摇杆活动范围边缘
mRockerPosition = MathUtils.getBorderPoint(mCtrlPoint, new Point((int)event.getX(), (int)event.getY()), mWheelRadius);
}
break;
case MotionEvent.ACTION_UP:
mRockerPosition = new Point(mCtrlPoint);
break;
}
Thread.sleep(40);
}else {
Thread.sleep(200);
}
} catch (Exception e) { }
invalidate();//更新布局
return true;
} }

使用Touch来检测手的触摸点,然后更新中心圆点的位置,再调用invalidate();来更新VIew的背景,实现OnDraw方法,来绘制图像

AppSingleRocker类:作为对比我用一个类继承SurfaceView然后实现背景透明

package com.example.test;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback; @SuppressLint("ViewConstructor")
public class AppSingleRocker extends SurfaceView implements Callback{
private SurfaceHolder mHolder;
private Paint mPaint;
public Point mRockerPosition; // 摇杆位置
private Point mCtrlPoint;// 摇杆起始位置
private int mRudderRadius = 25;// 摇杆半径
private int mWheelRadius = 80;// 摇杆活动范围半径
private int batmapHW = 160;
private int batmap2HW = 40;
int isHide = 0;
Bitmap bitmap,bitmap2;
float scale;
private SingleRudderListener listener = null; //事件回调接口
public static final int ACTION_RUDDER = 1, ACTION_ATTACK_DEVICEMOVE = 2, ACTION_STOP = 3, ACTION_ATTACK_CAMERAMOVE = 4;
public AppSingleRocker(Context context, AttributeSet attrs) {
super(context, attrs);
this.setKeepScreenOn(true);
scale = context.getResources().getDisplayMetrics().density;
mRudderRadius = dip2px(15);// 摇杆半径
mWheelRadius = dip2px(45);// 摇杆活动范围半径
mCtrlPoint = new Point((mRudderRadius + mWheelRadius), (mRudderRadius + mWheelRadius));// 摇杆起始位置
batmapHW = (mWheelRadius+mRudderRadius) * 2;
batmap2HW = mRudderRadius * 2;
mHolder = getHolder();
mHolder.addCallback(this);
mPaint = new Paint();
mPaint.setAntiAlias(true);
setFocusable(true);
setFocusableInTouchMode(true);
mRockerPosition = new Point(mCtrlPoint);
setZOrderOnTop(true);
mHolder.setFormat(PixelFormat.TRANSPARENT);//设置背景透明
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.joystick_l_pad);
bitmap = Bitmap.createScaledBitmap(bitmap, batmapHW, batmapHW, false);
bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.print2);
bitmap2 = Bitmap.createScaledBitmap(bitmap2,batmap2HW,batmap2HW, false);
} //获取屏幕的宽度,高度和密度以及dp / px
public void getDisplayMetrics() { }
public int dip2px(float dpValue) {
return (int)(dpValue * scale + 0.5f);
}
//回调接口
public interface SingleRudderListener {
void onSteeringWheelChanged(int action,int angle);
} //设置回调接口
public void setSingleRudderListener(SingleRudderListener rockerListener) {
listener = rockerListener;
} int len;
@Override
public boolean onTouchEvent(MotionEvent event) {
try {
if (isHide == 0) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
len = MathUtils.getLength(mCtrlPoint.x, mCtrlPoint.y, event.getX(), event.getY());
//如果屏幕接触点不在摇杆挥动范围内,则不处理
if(len > mWheelRadius) {
return true;
}
break;
case MotionEvent.ACTION_MOVE:
len = MathUtils.getLength(mCtrlPoint.x, mCtrlPoint.y, event.getX(), event.getY());
if(len <= mWheelRadius) {
//如果手指在摇杆活动范围内,则摇杆处于手指触摸位置
mRockerPosition.set((int)event.getX(), (int)event.getY());
}else{
//设置摇杆位置,使其处于手指触摸方向的 摇杆活动范围边缘
mRockerPosition = MathUtils.getBorderPoint(mCtrlPoint, new Point((int)event.getX(), (int)event.getY()), mWheelRadius);
}
if(listener != null) {
float radian = MathUtils.getRadian(mCtrlPoint, new Point((int)event.getX(), (int)event.getY()));
listener.onSteeringWheelChanged(ACTION_RUDDER, getAngleCouvert(radian));
}
break;
case MotionEvent.ACTION_UP:
mRockerPosition = new Point(mCtrlPoint);
if (listener != null) {
listener.onSteeringWheelChanged(ACTION_STOP, 0);
}
break;
}
Canvas_OK();
Thread.sleep(60);
}else {
Thread.sleep(200);
}
} catch (Exception e) { }
return true;
} public void singleRockerUp(){
mRockerPosition = new Point(mCtrlPoint);
listener.onSteeringWheelChanged(ACTION_STOP, 0);
}
//获取摇杆偏移角度 0-360°
private int getAngleCouvert(float radian) {
int tmp = (int)Math.round(radian/Math.PI * 180);
if(tmp < 0) {
return -tmp;
}else{
return 180 + (180 - tmp);
}
} public void surfaceCreated(SurfaceHolder holder) {
Canvas_OK();
} public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) { } public void surfaceDestroyed(SurfaceHolder holder) { }
// 设置是否隐藏
public void Hided(int opt)
{
isHide = opt;
Canvas_OK();
} public void setHided(int opt){
isHide = opt;
}
/**
* 返回圆盘是否隐藏
* @return
*/
public int getIsHided(){
return isHide;
}
//绘制图像
public void Canvas_OK(){
Canvas canvas = null;
try {
if (isHide == 0) {
canvas = mHolder.lockCanvas();
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);//清除屏幕
canvas.drawBitmap(bitmap, mCtrlPoint.x - mWheelRadius - mRudderRadius, mCtrlPoint.y - mWheelRadius - mRudderRadius, mPaint);
canvas.drawBitmap(bitmap2, mRockerPosition.x - mRudderRadius, mRockerPosition.y - mRudderRadius, mPaint);
}else {
canvas = mHolder.lockCanvas();
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);//清除屏幕
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(canvas != null) {
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}

activity_main这个是我的布局文件:

<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <com.example.test.Jockey_Left
android:layout_width="120dp"
android:layout_height="120dp"
android:id="@+id/left_jockey"
android:background="@drawable/joystick_l_pad"
></com.example.test.Jockey_Left> <Button
android:layout_width="60dp"
android:layout_height="60dp"
/> <com.example.test.AppSingleRocker
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
></com.example.test.AppSingleRocker>
<Button
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>

MainActivity这个是显示的Activity

package com.example.test;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu; public class MainActivity extends Activity { Jockey_Left jockey_left; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
jockey_left = (Jockey_Left)findViewById(R.id.left_jockey);
jockey_left.init(getResources().getDisplayMetrics().density);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
} }

显示效果如下图所示:

看效果图明显:

1.左上角的Button没有被覆盖,而右下角的Button被覆盖掉

2.这两个圆盘都是使用相同的图片,但是右下角有明显的锯齿,而左上角的没有

3.唯一不足的就是左上角流畅度不如右下角的

所以如果绘图区域要求矩形最好选用SurfaceVIew,因为这样提高程序流畅度,如果 要求圆盘而且不能覆盖其他的组件,选用继承View,重新实现。

源码下载地址:http://download.csdn.net/detail/jwzhangjie/5816135 这里同时实现了圆盘的功能

解决SurfaceView设置透明造成覆盖其他组件的替代方案的更多相关文章

  1. 解决SurfaceView调用setZOrderOnTop(true)遮挡其他控件的问题

    SurfaceView遮挡其他控件的项目背景: 最近在做播放器项目,由于底层实现是用Surface和OpenGL切换渲染,所以在布局里面同时使用了GLSurfaceView和SurfaceView,同 ...

  2. 解决css设置背景透明,文字不透明

    设置元素的透明度:  -moz-opacity:0.8; /*在Firefox中设置元素透明度  filter: alpha(opacity=80); /*ie使用滤镜设置透明   但是当我们对一个标 ...

  3. 取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏

    取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏,在MainActivity中添加以下代码: getWindow().clearFlags(WindowManager.LayoutP ...

  4. ubuntu 18.04配置静态ip,解决无法上网问题,解决resolv.conf配置文件被覆盖

    Netplan 是 Ubuntu 17.10 中引入的一种新的命令行网络配置实用程序,用于在 Ubuntu 系统中轻松管理和配置网络设置. 它允许您使用 YAML 格式的描述文件来抽像化定义网络接口的 ...

  5. Jtabbedpane设置透明、Jpanel设置透明

    摘自 https://zhidao.baidu.com/question/983204331427010139.html java中如何设置Jtabbedpane为透明 20 在Jtabbedpane ...

  6. vue覆盖UI组件样式不生效

    检查检查是不是加了scoped 在vue中,我们需要引用子组件,包括ui组件(element.iview). 但是在父组件中添加scoped之后,在父组件中书写子组件的样式是无效果的. 去掉scope ...

  7. 解决vue 绑定事件会覆盖默认参数的问题

    解决vue 绑定事件会覆盖默认参数的问题 在使用一些ui框架的时候,某些组件的框架中的事件所规定的参数不能满足实际开发的需要,但是直接传入参数会把默认的参数覆盖掉 解决方法:将参数放入箭头函数中,传递 ...

  8. 解决 window server2008 r2 没有注册Ofiice组件的方法

    解决 window server2008  r2 没有注册Ofiice组件的方法   .NET下在用Microsoft.Office.Interop.Excel及word 操作Excel和Word时, ...

  9. Android设置透明、半透明等效果

    设置透明效果 大概有三种 1.用android系统的透明效果Java代码 android:background="@android:color/transparent"  例如 设 ...

随机推荐

  1. Webbrowser判断页面加载完成

    Webbrowser 请求加载页面,页面中包含各种资源,不能够很准确的判断加载是否完成,需要通过特定的方法判断. 1.使用计数器判断页面是否加载完成.精准可控. // 计数器 ; // 添加事件响应函 ...

  2. 转;VC++中Format函数详解

    Format是一个很常用,却又似乎很烦的方法,以下是它的完整概貌,以供大家查询之用: 一.字符串 首先看它的声明: function Format(const Format: string; cons ...

  3. strnclmp和strlen函数的用法

    一.strncmp 函数 函数原型: 1.函数原型:int strncmp (const char *s1, const char *s2, size_t  n) 2.头文件: <string. ...

  4. TOP 100 MISSPELT/MISSPELLED WORDS IN ENGLISH

    acceptable accidentally accommodate acquire  acquit a lot amateur apparent argument atheist believe ...

  5. 仿QQ5.0以上新版本侧滑效果

    1.此效果使用了csdn大神孙国威的代码案例在此感谢附上参考博客地址: http://blog.csdn.net/manoel/article/details/39013095/#plain 2.sl ...

  6. MVC4重复提交

    http://blog.sina.com.cn/s/blog_712ff52a0101f38r.html http://blog.csdn.net/litao2/article/details/868 ...

  7. Android addView动态给Activity添加View组件

    本文主要讲述如何动态给UI界面添加布局和控件,在编程的时候很多时候需要动态显示一些内容,在动态添加View的时候,主要使用addView方法. 1. addView方法简介 在Android 中,可以 ...

  8. 【转】DELL戴尔N4050笔记本拆机(图文)

    原文网址:http://www.ywxydn.com/1047.html

  9. NOI2010 航空管制

    http://www.lydsy.com/JudgeOnline/problem.php?id=2535 贪心. 对于第1个问,我们先建立拓扑图,对于如果a必须在b前起飞,那么连有向边b->a, ...

  10. Raid1源代码分析--一些补充

    Raid1的源码的读.写.同步,在本系列博客中都已经分析完成.除了barrier机制要专门拿出来分析(下一篇会写)以外,有一些问题值得思考和注意,分析如下. 1.freeze_array是如何做的? ...