简体   繁体   English

Android自定义形状按钮

[英]Android Custom Shape Button

How can i make a custom shaped clickable view or button in Android? 如何在Android中制作自定义形状的可点击视图或按钮?

When I click , I want to avoid touching on an empty area . 当我点击时,我想避免触摸空白区域。

在此输入图像描述

please help. 请帮忙。 Thank you. 谢谢。

Interesting question. 有趣的问题。 I tried some solutions and this is what I found that has the same result of what you are trying to achieve. 我尝试了一些解决方案,这是我发现的,与你想要实现的结果相同。 The solution below resolves 2 problems: 下面的解决方案解决了2个问题:

  1. Custom shape as you presented it 你提出的自定义形状
  2. The top right side of the button shouldn't be clickable 按钮的右上角不应该是可点击的

So this is the solution in 3 steps: 所以这是3个步骤的解决方案:

Step 1 步骤1

Create two shapes. 创建两个形状。

  • First simple rectangle shape for the button: shape_button_beer.xml 按钮的第一个简单矩形形状: shape_button_beer.xml

     <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <gradient android:angle="90" android:endColor="#C5D9F4" android:startColor="#DCE5FD" /> <corners android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" android:topLeftRadius="5dp" > </corners> </shape> 
  • Second shape is used as mask for the top right side of the button: shape_button_beer_mask.xml . 第二个形状用作按钮右上角的掩码: shape_button_beer_mask.xml It is simple circle with black solid color. 它是黑色纯色的简单圆圈。

     <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <solid android:color="#000000" /> </shape> 

Step 2 第2步

In your main layout add the button by next approach: 在主布局中,按下一种方法添加按钮:

  • RelativeLayout is the container of this custom button RelativeLayout是此自定义按钮的容器
  • First LinearLayout is the blue button with beer icon and text inside 第一个LinearLayout是蓝色按钮,里面有啤酒图标和文字
  • Second ImageView is the mask above the blue button. 第二个ImageView是蓝色按钮上方的掩码。 And here comes dirty trick: 这里有肮脏的伎俩:
    1. Margins are negative to set the mask in the right place 在正确的位置设置遮罩的边距为负
    2. We define id to be able override on click (see step 3) 我们定义id可以在点击时覆盖(参见步骤3)
    3. android:soundEffectsEnabled="false" - such that user will not feel that he pressed on something. android:soundEffectsEnabled="false" - 这样用户就不会觉得他按下了某些东西。

The XML: XML:

    <!-- Custom Button -->
    <RelativeLayout
        android:layout_width="120dp"
        android:layout_height="80dp" >

        <LinearLayout
            android:id="@+id/custom_buttom"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/shape_button_beer" >

            <!-- Beer icon and all other stuff -->

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="15dp"
                android:src="@drawable/beer_icon" />
        </LinearLayout>

        <ImageView
            android:id="@+id/do_nothing"
            android:layout_width="120dp"
            android:layout_height="100dp"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_marginRight="-50dp"
            android:layout_marginTop="-50dp"
            android:background="@drawable/shape_button_beer_mask"
            android:soundEffectsEnabled="false" >
        </ImageView>
    </RelativeLayout>
    <!-- End Custom Button -->

Step 3 第3步

In your main activity you define on click events for both: button and the mask as follow: 在您的主要活动中,您可以在以下两个点击事件中定义:按钮和掩码,如下所示:

LinearLayout customButton = (LinearLayout) findViewById(R.id.custom_buttom);
customButton.setOnClickListener(new View.OnClickListener()
{
    @Override
    public void onClick(View arg0)
    {
        Toast.makeText(getApplicationContext(), "Clicked", Toast.LENGTH_SHORT).show();
    }
});

// Mask on click will do nothing
ImageView doNothing = (ImageView) findViewById(R.id.do_nothing);
doNothing.setOnClickListener(new View.OnClickListener()
{
    @Override
    public void onClick(View arg0)
    {
        // DO NOTHING
    }
});

That's it. 而已。 I know that is not a perfect solution but in your described use case it could help. 我知道这不是一个完美的解决方案,但在您描述的用例中它可以提供帮助。 I have tested it on my mobile and this is how it looks when you click on the blue area and nothing will happen on other areas: 我已经在我的手机上测试了它,这就是当你点击蓝色区域时它看起来的样子,其他区域什么都不会发生:

  • 在此输入图像描述

Hope it helped somehow :) 希望它有所帮助:)

Use OnTouch instead of OnClick and check the alpha value of image you have used in the button.If its not equal to zero, do whatever you want. 使用OnTouch而不是OnClick并检查您在按钮中使用的图像的alpha值。如果它不等于零,请执行您想要的任何操作。 Check the followig code, 检查以下代码,

final Bitmap bitmap;  //Declare bitmap     
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.TheImage);


public boolean onTouch(View v, MotionEvent event) {

        int eventPadTouch = event.getAction();
        float iX=event.getX();
    float iY=event.getY();

        switch (eventPadTouch) {

            case MotionEvent.ACTION_DOWN:
                if (iX>=0 & iY>=0 & iX<bitmap.getWidth() & iY<bitmap.getHeight()) { //Makes sure that X and Y are not less than 0, and no more than the height and width of the image.                
                    if (bitmap.getPixel((int) iX, (int) iY)!=0) {
                        // actual image area is clicked(alpha not equal to 0), do something 
                    }               
                }
                return true;                
        }           
        return false;
}

u can try this one: 你可以尝试这个:

        <Button
        android:id="@+id/logout"
        android:layout_width="240dp"
        android:layout_height="28dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="ContactsDetails"
        android:textColor="#ffffff" android:layout_marginLeft="50dp" android:background="@drawable/round"/>

and create round.xml file in drawable folder: 并在drawable文件夹中创建round.xml文件:

        <?xml version="1.0" encoding="utf-8"?>
      <shape xmlns:android="http://schemas.android.com/apk/res/android"
      android:shape="rectangle" android:padding="0dp" android:useLevel = "false">
    <!-- you can use any color you want I used here gray color-->
     <solid android:color="#ABABAB"/> 
       <corners
       android:bottomRightRadius="0dp"
         android:bottomLeftRadius="0dp"
       android:topLeftRadius="0dp"
      android:topRightRadius="70dp"/>
       </shape>

use layer-list, You can design any shape any gradient button tops here is example 使用图层列表,您可以设计任何形状任何渐变按钮顶部这里是示例

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
            <corners

                android:topLeftRadius="0dp"
                android:topRightRadius="0dp"
                android:bottomLeftRadius="2dp"
                android:bottomRightRadius="15dp"
                />            
            <!-- The border color -->
            <solid android:color="#ffffff" />
        </shape>
    </item>

    <item android:right="2dp"
        android:left="2dp"
        android:bottom="2dp">
            <shape>            
            <gradient                
                android:startColor="#002a36"
                android:centerColor="#457c8e"
                android:endColor="#e6ffff"               
                android:angle="90" 
                  android:centerY="1"
                android:centerX="0.5"           
                />          

            <corners

                android:topLeftRadius="0dp"
                android:topRightRadius="0dp"
                android:bottomLeftRadius="2dp"
                android:bottomRightRadius="15dp"
                />            
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" 
                />                        
        </shape>
    </item>
</layer-list> 

use -ve radius values to make button shape as u mentioned 如上所述,使用-ve radius值来制作按钮形状

I had a similar problem but I did not want to depend on code behind to examine the pixel value. 我有类似的问题,但我不想依赖代码来检查像素值。 I wanted a simple way (not class overloading) to constrain a touch event to only a sub portion of a drawable. 我想要一种简单的方法(不是类重载)来将触摸事件约束到drawable的子部分。 Below I use a LinearLayout for the drawable and then inside that I put a transparent button (with text). 下面我使用LinearLayout作为drawable然后在里面我放了一个透明按钮(带文字)。 I can adjust the margin of the button to position the clickable area. 我可以调整按钮的边距来定位可点击区域。

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:background="@drawable/circle">
        <Button
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:id="@+id/btnTimer1"
            android:text="0:00"
            android:textColor="#ffffff"
            android:textSize="22dp"
            android:layout_margin="20dp"
            android:background="@android:color/transparent"/>
    </LinearLayout>

Best and easiest solution (as4me) I found here - it is subclassed Button and thus it supports selector. 我在这里找到的最好和最简单的解决方案(as4me) - 它是子类Button ,因此它支持选择器。 So all you need to do is to draw/add corresponding pngs for every button state to use selector and declare onClick in xml or add OnClickListener in code and you are ready to go. 因此,您需要做的就是为每个按钮状态绘制/添加相应的png以使用选择器并在xml中声明onClick或在代码中添加OnClickListener,您就可以开始了。

Rather than doing all those changes, you should use frame layout at the portion that surrounds the button, and mask the top right portion with some thingy(circular, like a rounded button) and assign no click listener on that part. 您应该在围绕按钮的部分使用框架布局,并使用一些东西(圆形,如圆形按钮)屏蔽右上部分,并在该部分上不指定任何单击侦听器,而不是进行所有这些更改。 This in effect hides the lower frame(ie your original button) and masks it with the non active part. 这实际上隐藏了下框架(即原始按钮)并用非活动部件遮住它。

I tried the answer by @Basim Sherif ( link ) and it works great however only if the button size is the same as the original image. 我尝试了@Basim Sherif( 链接 )的答案,但是只有当按钮大小与原始图像相同时,它才能正常工作。 If the button was stretched up then the clickable region will be smaller and if the button was set to a smaller size the clickable region will be bigger than the actual button. 如果按钮被拉伸,则可点击区域将变小,如果按钮设置为较小尺寸,则可点击区域将大于实际按钮。

The solution is simple which is to scale the iX and iY values to match the original bitmap. 解决方案很简单,即缩放iX和iY值以匹配原始位图。

And here is my modified version of the code: 这是我修改后的代码版本:

final Bitmap bitmap;  //Declare bitmap     
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.TheImage);

public boolean onTouch(View v, MotionEvent event) {

    int eventPadTouch = event.getAction();
    float iX=event.getX();
    float iY=event.getY();

    // Get the dimensions used in the view
    int realW = this.getWidth();
    int realH = this.getHeight();

    // Get the dimensions of the actual image
    int bitmapW = bitmap.getWidth();
    int bitmapH = bitmap.getHeight();

    // Scale the coordinates from the view to match the actual image
    float scaledX = iX * bitmapW / realW;
    float scaledY = iY * bitmapH / realH;

    switch (eventPadTouch) {
        case MotionEvent.ACTION_DOWN:
            if (scaledX >= 0 & scaledY >= 0 & scaledX < bitmap.getWidth() & scaledY < bitmap.getHeight()) { //Makes sure that X and Y are not less than 0, and no more than the height and width of the image.                
                if (bitmap.getPixel((int) scaledX, (int) scaledY)!=0) {
                    // actual image area is clicked(alpha not equal to 0), do something 
                }
            }
            return true;
    }
    return false;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM