解决SurfaceView设置透明造成覆盖其他组件的替代方案
之前在项目里面绘制摇杆圆盘使用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设置透明造成覆盖其他组件的替代方案的更多相关文章
- 解决SurfaceView调用setZOrderOnTop(true)遮挡其他控件的问题
SurfaceView遮挡其他控件的项目背景: 最近在做播放器项目,由于底层实现是用Surface和OpenGL切换渲染,所以在布局里面同时使用了GLSurfaceView和SurfaceView,同 ...
- 解决css设置背景透明,文字不透明
设置元素的透明度: -moz-opacity:0.8; /*在Firefox中设置元素透明度 filter: alpha(opacity=80); /*ie使用滤镜设置透明 但是当我们对一个标 ...
- 取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏
取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏,在MainActivity中添加以下代码: getWindow().clearFlags(WindowManager.LayoutP ...
- ubuntu 18.04配置静态ip,解决无法上网问题,解决resolv.conf配置文件被覆盖
Netplan 是 Ubuntu 17.10 中引入的一种新的命令行网络配置实用程序,用于在 Ubuntu 系统中轻松管理和配置网络设置. 它允许您使用 YAML 格式的描述文件来抽像化定义网络接口的 ...
- Jtabbedpane设置透明、Jpanel设置透明
摘自 https://zhidao.baidu.com/question/983204331427010139.html java中如何设置Jtabbedpane为透明 20 在Jtabbedpane ...
- vue覆盖UI组件样式不生效
检查检查是不是加了scoped 在vue中,我们需要引用子组件,包括ui组件(element.iview). 但是在父组件中添加scoped之后,在父组件中书写子组件的样式是无效果的. 去掉scope ...
- 解决vue 绑定事件会覆盖默认参数的问题
解决vue 绑定事件会覆盖默认参数的问题 在使用一些ui框架的时候,某些组件的框架中的事件所规定的参数不能满足实际开发的需要,但是直接传入参数会把默认的参数覆盖掉 解决方法:将参数放入箭头函数中,传递 ...
- 解决 window server2008 r2 没有注册Ofiice组件的方法
解决 window server2008 r2 没有注册Ofiice组件的方法 .NET下在用Microsoft.Office.Interop.Excel及word 操作Excel和Word时, ...
- Android设置透明、半透明等效果
设置透明效果 大概有三种 1.用android系统的透明效果Java代码 android:background="@android:color/transparent" 例如 设 ...
随机推荐
- tcpdump使用和TCP/IP包分析
关于tcpdump如何抓包,本文不再总结,可以查看 tcpdump的官方地址查看http://www.tcpdump.org 本文重点记录两个部分: 第一部分:tcpdump所抓包 ...
- nodejs 记入
1. vs2015 使用最新的 nodejs refer : http://josharepoint.com/2016/05/04/how-to-configure-visual-studio-201 ...
- PCB走线和过孔的过流能力
PCB走线的载流能力与以下因素有关:线宽.线厚(铜箔厚度).容许温升.PCB走线越宽,载流能力越大. 近似计算公式: I=KT0.44A0.75 (K为修正系数,一般覆铜线在内层时取0.024,在外层 ...
- Eclipse Android源代码新下载方法及关联
一.下载Android源代码 Android源代码从4.0后就可以使用SDK Manager进行下载,打开SDK Manager就可以看到,已4.4为例: 关联Android源代码 但是老是提示下载失 ...
- Linux sar使用
[root@ywcrmdb ~]# sar -d 1 10 Linux 2.6.32-220.el6.x86_64 (ywcrmdb) 2014年04月19日 _x86_64_ (4 CPU) 1 ...
- FFT修正
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #inc ...
- HDU-3661(贪心)
Problem Description In a factory, there are N workers to finish two types of tasks (A and B). Each t ...
- linux0.12 链接过程
终于编译OK了..可链接就是一大堆错误 问题1: boot/head.o: In function `startup_32': (.text+0x10): undefined reference to ...
- 【KMP+DP】Count the string
KMP算法的综合练习 DP很久没写搞了半天才明白.本题结合Next[]的意义以及动态规划考察对KMP算法的掌握. Problem Description It is well known that A ...
- pyqt4制作透明无边框窗体
用PyQt做了一个无边框登陆窗口,效果如下: 下面是代码: # -*- coding: utf-8 -*- from PyQt4 import QtGui ,Qt ,QtCore image=QtGu ...