[英]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个问题:
So this is the solution in 3 steps: 所以这是3个步骤的解决方案:
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>
In your main layout add the button by next approach: 在主布局中,按下一种方法添加按钮:
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 -->
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.