创建不规则形状的ImageButton不同的点击状态 [英] Creating irregular shaped ImageButton with different click states

查看:421
本文介绍了创建不规则形状的ImageButton不同的点击状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个选择为pressed和非pressed状态的ImageButton的,这工作得很好。

但按钮具有不规则的形状,我只希望它可以点击其中基础矩形图像是不透明的。

所以,我实现了一个OnTouchListener,检查触摸事件的坐标对位图的像素值(在这里的第一个答案说明:<一href="http://stackoverflow.com/questions/8224852/how-to-create-an-irregular-shaped-imagebutton-where-transparent-part-of-image-is">link). 这工作,在决定是否按钮是pressed逻辑方面,但现在该按钮的图像不会更改为pressed形象了。

下面是我:

选择XML文件:

 &LT; XML版本=1.0编码=UTF-8&GT?;
&LT;选择的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android&GT;
    &LT;项目的android:STATE_ pressed =真正的机器人:可绘制=@可绘制/ button_start_call_ pressed/&GT;
    &LT;项目机器人:可绘制=@可绘制/ button_start_call_normal/&GT;
&LT; /选择器&GT;
 

在布局部分透明的ImageButton:

 &LT;的ImageButton
    机器人:ID =@ + ID / dashboardStartCallButton
    机器人:背景=@空
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT
    机器人:SRC =@可绘制/ start_call_button_selector
     /&GT;
 

在活动:

 公共无效的onCreate(包savedInstance){
   super.onCreate(savedInstance);
   ...
   的ImageButton startCallButton =(的ImageButton)this.findViewById(R.id.dashboardStartCallButton);
   startCallButton.setOnTouchListener(新OnTouchListener(){
        @覆盖
        公共布尔onTouch(视图V,MotionEvent事件){
            返回OnStartCallButtonTouch(五,事件);
        }
    });
}


公共布尔OnStartCallButtonTouch(视图V,MotionEvent事件)
{
    位图TheBitmap = BitmapFactory.de codeResource(getResources(),R.drawable.button_start_call_normal);
    INT eventPadTouch = event.getAction();
    INT的iX =(INT)event.getX();
    INT IY =(int)的event.getY();
    开关(eventPadTouch){
        案例MotionEvent.ACTION_DOWN:
            如果(IX&GT; = 0&安培; IY&GT; = 0&安培;&的iX其中; TheBitmap.getWidth()及IY&其中; TheBitmap.getHeight()){
                如果(TheBitmap.getPixel(IX,IY)!= 0){
                    onStartCallButtonClicked(五);
                    返回false;
                }
            }
    }
    返回true;
}
 

解决方案

我想你实际上是在寻找这样的:

<一个href="http://grep$c$c.com/file/repository.grep$c$c.com/java/ext/com.google.android/android/1.5_r4/android/view/View.java#View.dispatchTouchEvent%28android.view.MotionEvent%29">View.dispatchTouchEvent(...)

您需要覆盖您的自定义按钮,该方法返回的的,如果点不在所需的区域。我建议你​​去了解它是这样的:

 公共静态MyButton类扩展的ImageButton {
    ...
    @覆盖
    公共布尔dispatchTouchEvent(MotionEvent事件){
        INT的iX =(INT)event.getX();
        INT IY =(int)的event.getY();
        // TODO或者用一个更复杂的,像素值的基础条件
        如果((IX&GT;!= 0&安培; IY&GT; = 0&安培;&的iX其中; TheBitmap.getWidth()及IY&其中; TheBitmap.getHeight())){
            返回false;
        }
        返回super.dispatchTouchEvent(事件)
    }
}
 

为什么不使用OnTouchListener :因为你需要通过打电话给View.onTouchEvent()(这是在super.dispatchTouchEvent(事件)完成),让浏览处理绘制状态(它在做的onTouchEvent ()使用View.refreshDrawableState()方法,另外还有一些比较复杂的逻辑存在)

为什么不能覆盖的onTouchEvent():由于View.dispatchTouchEvent()有一个条件,如果有一个OnTouchListener,然后让听者处理一切并返回true。所以,如果您以后设置OnTouchListener为某种原因按钮,在您的onTouchEvent基于坐标的条件()将不会得到遏制,因为的onTouchEvent()将永远不会被调用。通过覆盖dispatchTouchEvent()你过滤倒是在最高层,并保留所有其他逻辑的地方 - 你可以添加任何侦听器的按钮,他们会工作,因为他们会为普通按钮,但只有当你的条件为真

I created an ImageButton with a selector for pressed and non-pressed states, and this works fine.

But the button has an irregular shape and I only want it clickable where the underlying rectangular image is non-transparent.

So I implemented an OnTouchListener that checks the touch event's co-ordinates against the Bitmap's pixel values (as described in the first answer here: link). This works, in terms of the logic deciding if the button was pressed, but now the image of the button doesn't change to the pressed image anymore.

Here is what I have:

Selector xml file:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_pressed="true" android:drawable="@drawable/button_start_call_pressed" />
    <item android:drawable="@drawable/button_start_call_normal" />
</selector>

Partly transparent ImageButton in the layout:

<ImageButton
    android:id="@+id/dashboardStartCallButton"
    android:background="@null"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/start_call_button_selector"
     />

In the Activity:

public void onCreate(Bundle savedInstance) {
   super.onCreate(savedInstance);
   ...
   ImageButton startCallButton = (ImageButton) this.findViewById(R.id.dashboardStartCallButton);
   startCallButton.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return OnStartCallButtonTouch(v,event);
        }           
    });
}


public boolean OnStartCallButtonTouch(View v, MotionEvent event)
{
    Bitmap TheBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.button_start_call_normal);
    int eventPadTouch = event.getAction();
    int iX = (int) event.getX();
    int iY = (int) event.getY();
    switch (eventPadTouch) {
        case MotionEvent.ACTION_DOWN:
            if (iX>=0 & iY>=0 & iX<TheBitmap.getWidth() & iY<TheBitmap.getHeight()) {                 
                if (TheBitmap.getPixel(iX,iY)!=0) {
                    onStartCallButtonClicked(v); 
                    return false; 
                } 
            }
    }           
    return true;
}

解决方案

I think you're actually looking for this:

View.dispatchTouchEvent(...)

You need to override this method in your custom button to return false if point is not in the desired area. I suggest you go about it like this:

public static class MyButton extends ImageButton {
    ...
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int iX = (int) event.getX();
        int iY = (int) event.getY();
        // TODO Or use a more sophisticated, pixel value-based condition
        if (!(iX>=0 & iY>=0 & iX<TheBitmap.getWidth() & iY<TheBitmap.getHeight())) {
            return false;
        }
        return super.dispatchTouchEvent(event)
    }
}

Why not use OnTouchListener: Because you need to call through to View.onTouchEvent() (which is done in super.dispatchTouchEvent(event)) to let View handle drawable states (it's done in onTouchEvent() using View.refreshDrawableState() method, and there's also some more rather complex logic there)

Why not override onTouchEvent(): Because in View.dispatchTouchEvent() there is a condition that if there is an OnTouchListener, then let the listener handle everything and return true. So if later on you set an OnTouchListener to the button for some reason, your coordinate-based condition in onTouchEvent() would not get checked, because onTouchEvent() would never get called. By overriding dispatchTouchEvent() you filter touches at the very top and leave all the other logic in place - you can add any listeners to the button and they will work as they would for normal button, but only when your condition is true.

这篇关于创建不规则形状的ImageButton不同的点击状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆