android中的多个复杂形状的按钮

时间:2015-08-06 14:50:09

标签: android android-fragments bitmap surfaceview android-selector

我希望那里的人可以帮助我。

我有一个活动,您可以从中选择一个。 10项。当单击一个项目时,我打开一个片段,其目的是让用户从8个不同的动作中做出选择。该片段包含多个按钮,必须尽快加载。

然而,要求是拥有这样的用户界面: complex_button

此图片中的每个黑暗部分和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事件。

我花了最后一周的时间寻找一种有效的方法,但我似乎无法找到答案。

你知道如何创建这个自定义形状的多按钮吗?我没有关于在哪里寻找什么以及寻找什么的想法......

帮助赞赏

0 个答案:

没有答案