(Android布局)解决方案在不规则形状图像的顶部放置按钮或获取图像特定区域的触摸检测(可触摸区域)?

时间:2013-08-25 19:57:28

标签: android android-layout button touch

在我的Android应用程序中,我在全球范围内有三个不规则形状,如下所示:

enter image description here

所以我将整个图像放在布局中。Globe is just an image .There is no role of globe here.现在我想在全球各个不规则形状的图像上放置一个按钮。

按钮总是长方形但I want to get touch event for irregular shape,not for rectangular area.那么如何在这三个不规则形状上放置三个按钮或者有任何解决方案?以便在活动中处理每个按钮的不同事件?

我不知道如何完成这项任务。请指导我。

有任何建议或意见吗?

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:1)

我没有测试过这个,但我认为它会起作用。我相信你必须调整它并进行更正。

创建背景图像的副本,其中三个按钮是三种不同的颜色,没有锯齿,所有其他像素都是纯黑色。它必须是PNG,因此它不会有JPG压缩工件。这将是你的面具。因为你只有三个按钮,所以你可以使用纯红色,绿色和蓝色。只要纵横比相同,它的分辨率可能低于原始图像。

Subclass ImageView并使用您的子类来绘制背景。将您的掩码图像的子类化版本作为位图传递。

class TouchMaskImageView extends ImageView {
    ...constructors

    public void setTouchMask(Bitmap mask){
        this.mMask = mask;
    }

    public interface OnTouchedListener{
        public void onTouched(MotionEvent event, int colorTouched);
        public void onTouchCanceled();
    }

    public void setOnTouchedListener(OnTouchedListener listener){
        this.mOnTouchedListener = listener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        if (mOnTouchedListener  != null && mMask != null ) {
            if (x >=0 && x < (float)getWidth() &&
                y >=0 && y < (float)getHeight()) {
                //Next two lines will be more complicated if 
                  // you aren't using scaleType fitXY
                int maskX = (int) x * mMask.getWidth() / getWidth();
                int maskY = (int) y * mMask.getWidth() / getHeight();
                int maskColor = mask.getPixel(maskX, maskY);
                mOnTouchedListener.onTouched(event, maskColor);
            } else if (event.getAction()==MotionEvent.UP){
                //released finger outside image view
                mOnTouchedListener.onTouchCanceled();
            }
        }
    }
}

现在您可以创建一个OnTouchedListener来处理类似于按钮的触摸逻辑。它需要跟踪状态。这是一个例子,但我不确定当有多点触摸时这是否会破坏。您可能还需要为第一个手指设置动作蒙版,并使用getActionMasked()而不是getAction()。

public void onTouched(MotionEvent event, int colorTouched){
    switch(mState){
    case STATE_WAITING:
        if (event.getAction()==MotionEvent.ACTION_DOWN){
            switch (colorTouched){
            case 0xffff0000: //red
                mTouchMaskImageView.setImageResource(R.drawable.redButtonDown);
                mState = STATE_LATCHED_RED;
                break;
            case 0xff00ff00: //green
                mTouchMaskImageView.setImageResource(R.drawable.greenButtonDown);
                mState = STATE_LATCHED_GREEN;
                break;
            case 0xff0000ff: //blue
                mTouchMaskImageView.setImageResource(R.drawable.blueButtonDown);
                mState = STATE_LATCHED_BLUE;
                break;
            }
        }
        break;
   case STATE_LATCHED_RED:
        switch (event.getAction()){
        case (MotionEvent.ACTION_MOVE):
            if (colorTouched = 0xffff0000)
                mTouchMaskImageView.setImageResource(R.drawable.redButtonDown);
            else
                mTouchMaskImageView.setImageResource(R.drawable.defaultImage);
            break;
        case (MotionEvent.ACTION_UP)
            if (colorTouched = 0xffff0000)
                performRedButtonAction();
            mTouchMaskImageView.setImageResource(R.drawable.defaultImage);
            mState = STATE_WAITING;
            break;
        }
        break;
   case etc. for other two latched colors...
        break;
   }
}

public void onTouchCanceled(){
    mTouchMaskImageView.setImageResource(R.drawable.defaultImage);
    mState = STATE_WAITING;
}

这有些粗糙,因为您需要四个不同的图像副本来表示四种可能的状态。如果您想节省一些内存并使其运行得更快,您可以尝试使用单独的图像视图设置布局,使三个按钮重叠在正确的位置,并针对图像更改进行定位。但这将是非常具有挑战性的,考虑到你必须使它完美地适合任何屏幕尺寸。

答案 1 :(得分:0)

FLAG_WINDOW_IS_OBSCURED旗帜过去对我来说效果很好,但可能需要一些合作才能做到正确。这可能值得一试,但说实话,我还不确定它究竟是如何确定什么是不被遮挡的,所以它可能不适用于此。

static OnTouchListener listenerMotionEvent = new OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if ( (motionEvent.getFlags() | MotionEvent.FLAG_WINDOW_IS_OBSCURED) != MotionEvent.FLAG_WINDOW_IS_OBSCURED ) {
            return false;
            // View is not obscured so we pass on the event
        }

        // Process the motion event here and return true if you consume it
};

答案 2 :(得分:0)

在Photoshop中切片图像,然后将该图像放在webview帮助中吗?

答案 3 :(得分:0)

从上面的答案中,我得到了提示,最后我得到了解决方案如下:

我所做的是:

在xml文件中使用RelativeLayout

使用ImageView,如下所示:

  <ImageView
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/glob2"
        android:layout_marginBottom="24dp"
        android:layout_marginLeft="80.5dp"
        android:contentDescription="@string/profile_picture_description"
        android:src="@drawable/pick_matches_background" />

这里我相应地设置了保证金(左/右/下/上)。

在活动中,

声明

Bitmap btmp; and
ImageView img;

在onCreate方法中,

 // initialized image view
img = (ImageView) findViewById(R.id.btn1);
img.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

       // call your method here

  }
});

StateListDrawable sdCreateTrip = (StateListDrawable) img
            .getDrawable();

btmp = ((BitmapDrawable) sdCreateTrip.getCurrent())
            .getBitmap();

你现在准备好了。