我希望那里的人可以帮助我。
我有一个活动,您可以从中选择一个。 10项。当单击一个项目时,我打开一个片段,其目的是让用户从8个不同的动作中做出选择。该片段包含多个按钮,必须尽快加载。
此图片中的每个黑暗部分和X都应是可点击的。当用户按下按钮时,我想要视觉反馈(部分变暗)。
问题是片段加载时间太长而且需要视觉反馈。以下是我已经尝试实现的目标:
我可以访问gimp中该图像的每个部分,因此我可以提取它的每一部分。
A)带有9个按钮的XML布局。我单独提取每个项目,为每个按钮创建一个选择器,并使用此类来调度onTouchEvent:
private Bitmap b;
private void init(){ //called in every constructor
b = drawableToBitmap(super.getBackground(), super.getMeasuredWidth(), super.getMeasuredHeight());
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
//TODO add Offset
if (b.getPixel(x,y) == Color.TRANSPARENT){
return false;
}
return super.dispatchTouchEvent(event);
}
public static Bitmap drawableToBitmap (Drawable drawable, int newWidth, int newHeight) {
Bitmap bitmap = null;
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if(bitmapDrawable.getBitmap() != null) {
return Bitmap.createScaledBitmap(bitmapDrawable.getBitmap(), newWidth, newHeight, true);
}
}
if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
这仅适用于最多2或3张照片,并且占用大量空间。在3个组件之后,按钮开始滞后....
B)我创建了一个surfaceView并分别绘制了图像的每个部分。稍后我可以使用位图引用来确定单击了哪个部分。
我意识到加载所有图像需要很长时间(即使是在单独的线程中完成),所以我决定以完全合成的状态显示图像。我用这个课:
/**
* Context for Views
*/
private Context context;
/**
* Thread for painting with 50Hz
*/
private DrawThread drawThread;
/**
* Boolean storage for indicating that start values has been set
*/
private boolean isInitialized = false;
/**
* Standard constructor required for android system
*
* @param ctx
* @param attrSet
*/
public BButtonView(Context ctx, AttributeSet attrSet) {
super(ctx, attrSet);
BitmapFactory.Options bitopt = new BitmapFactory.Options();
bitopt.inMutable = true;
bitopt.inPreferredConfig = Bitmap.Config.RGB_565;
context = ctx;
base = BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_all, bitopt);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
this.setOnTouchListener(this);
}
/**
* Method defining the behavior of this view. It changes the trigger level and the zero level line
*
* @param v
* @param event
* @return
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
/**
* This class paints on the SurfaceViews canvas
*/
public class DrawThread extends Thread {
/**
* State variable for endless loop
*/
boolean mRun;
/**
* Surface on which will be painted
*/
Canvas mcanvas;
/**
* SurfaceHolder for getting and locking the canvas
*/
SurfaceHolder surfaceHolder;
/**
* Context for this view
*/
Context context;
/**
* Reference to the view to be painted on
*/
BButtonView bButtonView;
/**
* Constructor for this class
*
* @param sholder
* @param ctx
* @param view
*/
public DrawThread(SurfaceHolder sholder, Context ctx, BButtonView view) {
surfaceHolder = sholder;
context = ctx;
mRun = false;
bButtonView = view;
}
/**
* Changes the state variable
*
* @param bRun
*/
void setRunning(boolean bRun) {
mRun = bRun;
}
/**
* This method will run on another Thread. It will refresh with 50Hz
*/
@Override
public void run() {
super.run();
while (mRun) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
surfaceHolder.setFormat(0x00000004); //RGB_565
mcanvas = surfaceHolder.lockCanvas();
if (mcanvas != null) {
bButtonView.doDraw(mcanvas);
surfaceHolder.unlockCanvasAndPost(mcanvas);
}
}
}
}
/**
* Override of the surface creation. Initializes the drawThread
*
* @param holder
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawThread = new DrawThread(holder, context, this);
drawThread.setRunning(true);
drawThread.start();
}
/**
* Will not be used
*
* @param holder
* @param format
* @param width
* @param height
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/**
* Frees the thread instance.
*
* @param holder
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
drawThread.setRunning(false);
boolean retry = true;
while (retry) {
try {
drawThread.join();
retry = false;
} catch (Exception e) {
Log.v("BButtonView", e.getMessage());
}
}
}
/**
* Method defining what will be drawn and in which order. Is called by drawerThread with 50Hz
*
* @param canvas
*/
void doDraw(Canvas canvas) {
/**Create Background color*/
canvas.drawColor(Color.WHITE);
Rect dst = new Rect(0, 0, getWidth(), getHeight());
Paint paint = new Paint(Color.WHITE);
canvas.drawBitmap(base, null, dst, paint);
init(canvas);
}
private Bitmap base;
private ArrayList<Bitmap> layers;
private void init(Canvas canvas) {
if (isInitialized)
return;
float h = canvas.getHeight();
float w = canvas.getWidth();
layers = new ArrayList<>();
BitmapFactory.Options bitopt = new BitmapFactory.Options();
bitopt.inMutable = true;
bitopt.inPreferredConfig = Bitmap.Config.RGB_565;
bitopt.inSampleSize = ImageCreationAndManipulation.calculateInSampleSize(bitopt, (int) w, (int) h);
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_base, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_a_default, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_b_default, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_c_default, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_d_default, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_e_default, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_f_default, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_g_default, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_h_default, bitopt));
layers.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.bbutton_m_default, bitopt));
//TODO generate PixelMap
isInitialized = true;
}
这是我到目前为止所拥有的。但是,片段加载速度非常慢,并且我没有实现onTouch-Behavior事件。
我花了最后一周的时间寻找一种有效的方法,但我似乎无法找到答案。
你知道如何创建这个自定义形状的多按钮吗?我没有关于在哪里寻找什么以及寻找什么的想法......
帮助赞赏