To get a Triangle Shaped Background for TextView - android

I'm trying to fix a triangle shaped background for a TextView as shown .
I'm using the following XML code:
<TextView
android:id="#+id/type_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="#drawable/triangle_bg"
android:padding="1dp"
android:text="Sponsors"
android:textColor="#ffffff" />
Here's the code for triangle_bg.xml
<item>
<rotate
android:fromDegrees="45"
android:pivotX="90%"
android:pivotY="-50%"
android:toDegrees="-45" >
<shape android:shape="rectangle" >
<stroke
android:width="1dp"
android:color="#android:color/transparent" />
<solid android:color="#00C6FF" />
</shape>
</rotate>
</item>
the resultant image in my xml using the above code looks as
Can anyone tell me how I can achieve the triangle background as shown in my first background..??
Thanks in Advance
I've an idea of placing an Image instead of using a textview. But I would like to know whether there is any option to use textview. Please help if any!!!

You can just use a custom drawable like the following:
public class TriangleDrawable extends Drawable {
#Override
public void draw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
Path path = new Path();
path.moveTo(0, 0);
path.lineTo(canvas.getWidth() / 2, canvas.getHeight());
path.lineTo(canvas.getWidth(), 0);
path.close();
canvas.drawPath(path, paint);
}
}
Set this as the background of your TextView
findViewById(R.id.text).setBackground(new TriangleDrawable());
and be sure to apply padding to left / right, since the drawable will only draw within the bounds of the TextView.
<TextView
style="#style/Base.TextAppearance.AppCompat.Body1"
android:paddingLeft="32dp"
android:paddingRight="32dp"
android:text="TEST"
android:id="#+id/text"/>

use an image with text sponsors as, you can't change the angles between two side in a rectangle in xml

Related

Programatically change background of Drawable, maintaining the corner radius

interview_timeline_row.xml
<LinearLayout
android:id="#+id/interviewTimelineIconLayout"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_marginTop="20dp"
android:background="#drawable/timeline_row_icon_layout_bg"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/interviewTimelineRowIcon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:adjustViewBounds="false"
android:cropToPadding="false"
android:padding="6dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
timeline_row_icon_layout_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="#dimen/_50sdp" />
<stroke android:width="1dp" android:color="#color/white" />
<solid android:color="#color/ic_rescheduled"/> //need to add this programatically
</shape>
InterviewTimeline.java
iconBg = row.findViewById(R.id.interviewTimelineIconLayout);
iconBg.setBackgroundColor(getResources().getColor(R.color.ic_rescheduled)); //this is the wrong way to go about it
I want to use the timeline_row_icon_layout_bg.xml in various places in my app, and it should have a different background color each time. If I use the iconBg.setBackgroundColor() method, then it ignores the radius and I have a square background color.
Since you are just using the shape to create a layout with rounded corners and a border, the first option is to wrap your LinearLayout inside a CardView and then apply to the card the corner radius, the stroke and the background color.
Otherwise you could use the MaterialShapeDrawable included in the Material Components Library to draw custom shapes.
Just remove from the LinearLayout the android:background:
<LinearLayout
android:id="#+id/interviewTimelineIconLayout"
android:layout_width=".."
android:layout_height="..
..>
<!-- ..... -->
</LinearLayout>
Then in your code you can apply a ShapeAppearanceModel. Something like:
float radius = getResources().getDimension(R.dimen.corner_radius);
LinearLayout linearLayout= findViewById(R.id.interviewTimelineIconLayout);
ShapeAppearanceModel shapeAppearanceModel = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius)
.build();
MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable(shapeAppearanceModel);
//Fill the LinearLayout with your color
shapeDrawable.setFillColor(ContextCompat.getColorStateList(this,R.color.yourColor));
//Stroke color and width
shapeDrawable.setStrokeWidth(2.0f);
shapeDrawable.setStrokeColor(...);
ViewCompat.setBackground(linearLayout,shapeDrawable);
In this way you easily change and set the color background and the stroke.
Copy your "timeline_row_icon_layout_bg.xml" file and rename it "timeline_row_icon_layout_bg_new.xml"
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="#dimen/_50sdp" />
<stroke android:width="1dp" android:color="#color/white" />
<solid android:color="#color/put_the_color_you_need" />
</shape>
And you can set background to layout:
iconBg.setBackgroundResource(R.drawable.timeline_row_icon_layout_bg_new);
set the background of LinearLayout programmatically.
val bgDrawable = resources.getDrawable(R.drawable.timeline_row_icon_layout_bg, null).apply{
colorFilter = PorterDuffColorFilter(
ResourcesCompat.getColor(resources, R.color.ic_rescheduled, null),
PorterDuff.Mode.SRC_IN
)
}
iconBg.background = bgDrawable
move the shape drawable timeline_row_icon_layout_bg to the drawable resource folder.

Android draw/add graphical border around a view [duplicate]

Is it possible to draw a border around an Android TextView?
You can set a shape drawable (a rectangle) as background for the view.
<TextView android:text="Some text" android:background="#drawable/back"/>
And rectangle drawable back.xml (put into res/drawable folder):
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#android:color/white" />
<stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>
You can use #android:color/transparent for the solid color to have a transparent background.
You can also use padding to separate the text from the border.
for more information see: http://developer.android.com/guide/topics/resources/drawable-resource.html
Let me summarize a few different (non-programmatic) methods.
Using a shape drawable
Save the following as an XML file in your drawable folder (for example, my_border.xml):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- View background color -->
<solid
android:color="#color/background_color" >
</solid>
<!-- View border color and width -->
<stroke
android:width="1dp"
android:color="#color/border_color" >
</stroke>
<!-- The radius makes the corners rounded -->
<corners
android:radius="2dp" >
</corners>
</shape>
Then just set it as the background to your TextView:
<TextView
android:id="#+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/my_border" />
More help:
Shape Drawable (Android docs)
Android Developer Tips & Tricks: XML Drawables (Part I)
Using a 9-patch
A 9-patch is a stretchable background image. If you make an image with a border then it will give your TextView a border. All you need to do is make the image and then set it to the background in your TextView.
<TextView
android:id="#+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/my_ninepatch_image" />
Here are some links that will show how to make a 9-patch image:
Draw 9-patch
Simple Nine-patch Generator
A simple guide to 9-patch for Android UI
Creating & Using 9-patch images in Android
What if I just want the top border?
Using a layer-list
You can use a layer list to stack two rectangles on top of each other. By making the second rectangle just a little smaller than the first rectangle, you can make a border effect. The first (lower) rectangle is the border color and the second rectangle is the background color.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Lower rectangle (border color) -->
<item>
<shape android:shape="rectangle">
<solid android:color="#color/border_color" />
</shape>
</item>
<!-- Upper rectangle (background color) -->
<item android:top="2dp">
<shape android:shape="rectangle">
<solid android:color="#color/background_color" />
</shape>
</item>
</layer-list>
Setting android:top="2dp" offsets the top (makes it smaller) by 2dp. This allows the first (lower) rectangle to show through, giving a border effect. You can apply this to the TextView background the same way that the shape drawable was done above.
Here are some more links about layer lists:
Understanding Android's <layer-list>
How to make bottom border in drawable shape XML selector?
Create borders on a android view in drawable xml, on 3 sides?
Using a 9-patch
You can just make a 9-patch image with a single border. Everything else is the same as discussed above.
Using a View
This is kind of a trick but it works well if you need to add a seperator between two views or a border to a single TextView.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textview1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- This adds a border between the TextViews -->
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#android:color/black" />
<TextView
android:id="#+id/textview2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Here are some more links:
How to draw a line in Android
How to put a horizontal divisor line between edit text's in a activity
How to add a horizontal 1px line above image view in a relative layout?
The simple way is to add a view for your TextView. Example for the bottom border line:
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:text="#string/title"
android:id="#+id/title_label"
android:gravity="center_vertical"/>
<View
android:layout_width="fill_parent"
android:layout_height="0.2dp"
android:id="#+id/separator"
android:visibility="visible"
android:background="#android:color/darker_gray"/>
</LinearLayout>
For the other direction borders, please adjust the location of the separator view.
I have solved this issue by extending the textview and drawing a border manually.
I even added so you can select if a border is dotted or dashed.
public class BorderedTextView extends TextView {
private Paint paint = new Paint();
public static final int BORDER_TOP = 0x00000001;
public static final int BORDER_RIGHT = 0x00000002;
public static final int BORDER_BOTTOM = 0x00000004;
public static final int BORDER_LEFT = 0x00000008;
private Border[] borders;
public BorderedTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public BorderedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BorderedTextView(Context context) {
super(context);
init();
}
private void init(){
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(4);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(borders == null) return;
for(Border border : borders){
paint.setColor(border.getColor());
paint.setStrokeWidth(border.getWidth());
if(border.getStyle() == BORDER_TOP){
canvas.drawLine(0, 0, getWidth(), 0, paint);
} else
if(border.getStyle() == BORDER_RIGHT){
canvas.drawLine(getWidth(), 0, getWidth(), getHeight(), paint);
} else
if(border.getStyle() == BORDER_BOTTOM){
canvas.drawLine(0, getHeight(), getWidth(), getHeight(), paint);
} else
if(border.getStyle() == BORDER_LEFT){
canvas.drawLine(0, 0, 0, getHeight(), paint);
}
}
}
public Border[] getBorders() {
return borders;
}
public void setBorders(Border[] borders) {
this.borders = borders;
}
}
And the border class:
public class Border {
private int orientation;
private int width;
private int color = Color.BLACK;
private int style;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getStyle() {
return style;
}
public void setStyle(int style) {
this.style = style;
}
public int getOrientation() {
return orientation;
}
public void setOrientation(int orientation) {
this.orientation = orientation;
}
public Border(int Style) {
this.style = Style;
}
}
Hope this helps someone :)
Simplest solution I've found (and which actually works):
<TextView
...
android:background="#android:drawable/editbox_background" />
You can set the border by two methods. One is by drawable and the second is programmatic.
Using Drawable
<shape>
<solid android:color="#color/txt_white"/>
<stroke android:width="1dip" android:color="#color/border_gray"/>
<corners android:bottomLeftRadius="10dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="10dp"
android:topRightRadius="0dp"/>
<padding android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip"/>
</shape>
Programmatic
public static GradientDrawable backgroundWithoutBorder(int color) {
GradientDrawable gdDefault = new GradientDrawable();
gdDefault.setColor(color);
gdDefault.setCornerRadii(new float[] { radius, radius, 0, 0, 0, 0,
radius, radius });
return gdDefault;
}
I was just looking at a similar answer-- it's able to be done with a Stroke and the following override:
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Paint strokePaint = new Paint();
strokePaint.setARGB(255, 0, 0, 0);
strokePaint.setTextAlign(Paint.Align.CENTER);
strokePaint.setTextSize(16);
strokePaint.setTypeface(Typeface.DEFAULT_BOLD);
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setStrokeWidth(2);
Paint textPaint = new Paint();
textPaint.setARGB(255, 255, 255, 255);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(16);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
canvas.drawText("Some Text", 100, 100, strokePaint);
canvas.drawText("Some Text", 100, 100, textPaint);
super.draw(canvas, mapView, shadow);
}
With the Material Components Library you can use the MaterialShapeDrawable.
<TextView
android:id="#+id/textview"
.../>
Then you can programmatically apply a MaterialShapeDrawable:
TextView textView = findViewById(R.id.textview);
MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable();
shapeDrawable.setFillColor(ContextCompat.getColorStateList(this,android.R.color.transparent));
shapeDrawable.setStroke(1.0f, ContextCompat.getColor(this,R.color....));
ViewCompat.setBackground(textView,shapeDrawable);
You can add something like this in your code:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#ffffff" />
<stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>
I found a better way to put a border around a TextView.
Use a nine-patch image for the background. It's pretty simple, the SDK comes with a tool to make the 9-patch image, and it involves absolutely no coding.
The link is http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch.
Check the link below to make rounded corners
http://androidcookbook.com/Recipe.seam?recipeId=2318
The drawable folder, under res, in an Android project is not restricted to bitmaps (PNG or JPG files), but it can also hold shapes defined in XML files.
These shapes can then be reused in the project. A shape can be used to put a border around a layout. This example shows a rectangular border with curved corners. A new file called customborder.xml is created in the drawable folder (in Eclipse use the File menu and select New then File, with the drawable folder selected type in the file name and click Finish).
The XML defining the border shape is entered:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="20dp"/>
<padding android:left="10dp" android:right="10dp" android:top="10dp" android:bottom="10dp"/>
<solid android:color="#CCCCCC"/>
</shape>
The attribute android:shape is set to rectangle (shape files also support oval, line, and ring). Rectangle is the default value, so this attribute could be left out if it is a rectangle being defined. See the Android documentation on shapes at http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape for detailed information on a shape file.
The element corners sets the rectangle corners to be rounded. It is possible to set a different radius on each corner (see the Android reference).
The padding attributes are used to move the contents of the View to which the shape is applied, to prevent the contents overlapping the
border.
The border color here is set to a light gray (CCCCCC hexadecimal RGB value).
Shapes also support gradients, but that is not being used here. Again, see the Android resources to see how a gradient is defined. The shape is applied to the laypout using android:background="#drawable/customborder".
Within the layout other views can be added as normal. In this example, a single TextView has been added, and the text is white (FFFFFF hexadecimal RGB). The background is set to blue, plus some transparency to reduce the brightness (A00000FF hexadecimal alpha RGB value). Finally the layout is offset from the screen edge by placing it into another layout with a small amount of padding. The full layout file is thus:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp">
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/customborder">
<TextView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Text View"
android:textSize="20dp"
android:textColor="#FFFFFF"
android:gravity="center_horizontal"
android:background="#A00000FF" />
</LinearLayout>
</LinearLayout>
I have a way to do it very simply, and I'd like to share it.
When I want to square mi TextViews, I just put them in a LinearLayout. I set the background color of my LinearLayout, and I add a margin to my TextView. The result is exactly as if you square the TextView.
You can set a shape drawable (a rectangle with corners) as background for the view.
<TextView android:background="#drawable/frame"/>
And rectangle drawable frame.xml (put into res/drawable folder):
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#android:color/white" />
<stroke android:width="1dip"
android:color="#3d4caf"/>
<corners android:radius="50dp"/>
</shape>
You can create custom background for your text view.
Steps
Go to your project.
Go to resources and right click to drawable.
Click on New -> Drawable Resource File
Give name to you file
Paste following code in the file
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="1dp"
android:color="#color/colorBlack" />
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<corners android:radius="6dp" />
<solid android:color="#ffffffff" />
</shape>
For your text view where you want to use it as backgroud,
android:background="#drawable/your_fileName"
Changing Konstantin Burov answer because not work in my case:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#android:color/white" />
<stroke android:width="2dip" android:color="#4fa5d5"/>
<corners android:radius="7dp"/>
</shape>
</item>
</selector>
compileSdkVersion 26 (Android 8.0),
minSdkVersion 21 (Android 5.0),
targetSdkVersion 26,
implementation 'com.android.support:appcompat-v7:26.1.0',
gradle:4.1
Here is my 'simple' helper class which returns an ImageView with the border. Just drop this in your utils folder, and call it like this:
ImageView selectionBorder = BorderDrawer.generateBorderImageView(context, borderWidth, borderHeight, thickness, Color.Blue);
Here is the code.
/**
* Because creating a border is Rocket Science in Android.
*/
public class BorderDrawer
{
public static ImageView generateBorderImageView(Context context, int borderWidth, int borderHeight, int borderThickness, int color)
{
ImageView mask = new ImageView(context);
// Create the square to serve as the mask
Bitmap squareMask = Bitmap.createBitmap(borderWidth - (borderThickness*2), borderHeight - (borderThickness*2), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(squareMask);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
canvas.drawRect(0.0f, 0.0f, (float)borderWidth, (float)borderHeight, paint);
// Create the darkness bitmap
Bitmap solidColor = Bitmap.createBitmap(borderWidth, borderHeight, Bitmap.Config.ARGB_8888);
canvas = new Canvas(solidColor);
paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
canvas.drawRect(0.0f, 0.0f, borderWidth, borderHeight, paint);
// Create the masked version of the darknessView
Bitmap borderBitmap = Bitmap.createBitmap(borderWidth, borderHeight, Bitmap.Config.ARGB_8888);
canvas = new Canvas(borderBitmap);
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawBitmap(solidColor, 0, 0, null);
canvas.drawBitmap(squareMask, borderThickness, borderThickness, clearPaint);
clearPaint.setXfermode(null);
ImageView borderView = new ImageView(context);
borderView.setImageBitmap(borderBitmap);
return borderView;
}
}
There are a lot of ways to add a border to a textView. The simplest one is by creating a custom drawable and setting it as android:background="#drawable/textview_bg" for your textView.
The textview_bg.xml will go under Drawables and can be something like this.
You can have a solid or a gradient background (or nothing if not required), corners to add a corner radius and stroke to add border.
textview_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="#dimen/dp_10"/>
<gradient
android:angle="225"
android:endColor="#FFFFFF"
android:startColor="#E0E0E0" />
<stroke
android:width="2dp"
android:color="#000000"/>
</shape>
This may help you.
<RelativeLayout
android:id="#+id/textbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#android:color/darker_gray" >
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_margin="3dp"
android:background="#android:color/white"
android:gravity="center"
android:text="#string/app_name"
android:textSize="20dp" />
</RelativeLayout
Create a border view with the background color as the color of the border and size of your text view. set border view padding as the width of the border. Set text view background color as the color you want for the text view. Now add your text view inside the border view.
Try this:
<shape>
<solid android:color="#color/txt_white"/>
<stroke android:width="1dip" android:color="#color/border_black"/>
</shape>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#android:color/black" />
this code enough you can place wherever you want
setBackground on your xml textview,
add rounded_textview.xml file into your drawable directory.
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#android:color/white" />
<stroke android:width="2dip" android:color="#4f5g52"/>
</shape>
set drawable file in textView background.
Actually, it is very simple. If you want a simple black rectangle behind the Textview, just add android:background="#android:color/black" within the TextView tags. Like this:
<TextView
android:textSize="15pt" android:textColor="#ffa7ff04"
android:layout_alignBottom="#+id/webView1"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:background="#android:color/black"/>

Eliminate gap in Drawable Shape line

I'm trying to eliminate a gap seen below. The Views are right up against each other so it seems that it is something in the drawable.
I can see that it is related to the width of the stroke but how can I eliminate this effect?
Note that this is just an MVCE and the actual use case requires that I use a line smaller than the View is high.
For the removal of doubt, I will only accept an answer that fixes it in the drawable xml. I don't want a layout driven work around, the layout supplied is just to expose the problem.
drawable/line.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke
android:width="5dp"
android:color="#ff0000"/>
</shape>
layout/example.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/line">
</View>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/line">
</View>
</LinearLayout>
Where does this gap come from in Drawable Shape line?
The class responsible for creating shape drawables is GradientDrawable.java
Let's take a look at the source code.
In the draw(Canvas canvas) method:
switch (st.mShape) {
case LINE: {
RectF r = mRect;
float y = r.centerY();
if (haveStroke) {
canvas.drawLine(r.left, y, r.right, y, mStrokePaint);
}
break;
}
}
A line is drawn from mRect.left to mRect.right
Now let's see where mRect is modified.
In the ensureValidRect() method:
Rect bounds = getBounds();
float inset = 0;
if (mStrokePaint != null) {
inset = mStrokePaint.getStrokeWidth() * 0.5f;
}
final GradientState st = mGradientState;
mRect.set(bounds.left + inset, bounds.top + inset, bounds.right - inset, bounds.bottom - inset);
As you can see an inset, equal to half the stroke width, is added.
This is where your gap comes from.
how can I eliminate this effect?
You can add your own negative inset (should be half of your stroke width)
drawable/line_inset.xml
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#drawable/line"
android:insetLeft="-2.5dp"
android:insetRight="-2.5dp"/>
Consider using a 9-patch drawable
The lines top and left define the stretch areas. You can see that I'm only stretching the empty space.
The lines right and bottom define the content area, in this case, all of the space.
Two solutions:
1) Change the shape declared in XML to a rectangle
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ff0000"/>
<size android:width="100dp" android:height="1dp"/>
</shape>
Then in your layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="0dp"
android:layout_height="5dp"
android:layout_weight="1"
android:background="#drawable/line">
</View>
<View
android:layout_width="0dp"
android:layout_height="5dp"
android:layout_weight="1"
android:background="#drawable/line">
</View>
</LinearLayout>
2) Take a different approach, and not create an XML drawable for the line
<View
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="#android:color/holo_red_light"/>
edit
You say you need the height of the view greater than the size of the line. You could use an image view and the src attribute in combination with the rectangle XML shape to get this effect:
<ImageView
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:src="#drawable/line">
</ImageView>
<ImageView
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:src="#drawable/line">
</ImageView>
If I wrap in a layer list and item, I can extend left and right. I don't need to worry about them going further than needed they'll still cropped to the edge. This combats the effect.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:left="-5dp"
android:right="-5dp"> <!-- negative stroke width -->
<shape android:shape="line">
<stroke
android:width="5dp"
android:color="#ff0000"/>
</shape>
</item>
</layer-list>

Android Custom Shape Button

How can i make a custom shaped clickable view or button in 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:
Custom shape as you presented it
The top right side of the button shouldn't be clickable
So this is the solution in 3 steps:
Step 1
Create two shapes.
First simple rectangle shape for the button: 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. 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
In your main layout add the button by next approach:
RelativeLayout is the container of this custom button
First LinearLayout is the blue button with beer icon and text inside
Second ImageView is the mask above the blue button. And here comes dirty trick:
Margins are negative to set the mask in the right place
We define id to be able override on click (see step 3)
android:soundEffectsEnabled="false" - such that user will not feel that he pressed on something.
The 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
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.
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:
<?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
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. Below I use a LinearLayout for the drawable and then inside that I put a transparent button (with text). 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. 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.
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(i.e. 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. 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.
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;
}

How to create a drawable that's square on the outside and has rounded corners inside?

I'm trying to create rounded corners on a MapView, and since there doesn't seem to be any way to do it by default, I'm basically overlaying a layout with a background over my map view, like so:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp" >
<RelativeLayout
android:id="#+id/map_holder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#drawable/panel_rounded_corner_transparent" />
</RelativeLayout>
My rounded corner drawable is defined like this:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#drawable/bg_rounded_corner_transparent" />
</selector>
and the drawable inside is defined as:
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid
android:color="#color/transparent" />
<stroke
android:width="1dp"
android:color="#color/darkgray" />
<corners
android:radius="5dp" />
</shape>
</item>
</layer-list>
However, the problem is that since the map ends up rectangular and the border is rounded, the corners of the map peek out from behind the corners of my makeshift border. How do I set a background color for only the outside of my border, while keeping the inside of the panel transparent?
To clarify, here are some screenshots.
This screenshot shows the map as originally "bounded" by the overlaid border:
This screenshot replaces the map with a red background, for greater clarity in seeing what the problem is:
As you can see, the red (and by extension, the map) bleeds outside the border.
I can add a 1dp padding to the map, but that doesn't entirely solve the issue as you can see here:
Since the corners are rounded, part of the map still leaks out. It's a lot better than the first option, but not perfect--there are 1 pixel dots at the corners.
As this screenshot shows, a padding of more than 1dp is not a solution since it creates another problem entirely:
Try extending the MapView like the following:
private class MyMapView extends MapView {
public MyMapView(Context context, String apiKey) {
super(context, apiKey);
}
#Override
public void draw(Canvas canvas) {
Path path = new Path();
RectF r = new RectF(0, 0, this.getWidth(), this.getHeight());
path.addRoundRect(r, 12, 12, Path.Direction.CW);
canvas.clipPath(path);
super.draw(canvas);
}
}
You might need to adjust the radius for path.addRoundRect()
Have you tried using the styleable elements? Take a look at this:
http://developer.android.com/reference/android/R.styleable.html#DrawableCorners_bottomLeftRadius
Hope this helps, this should solve your problem :)
hi there i play around for a few hours with this and here is my solution for a ImageView with transparent frame (oval) inside and solid color outside. I know it is a oval shape but it also works with rect.
Implement a FrameLayout with two children inside. So the shape will overlapping the ImageView:
<FrameLayout
android:id="#+id/testLinearLayout"
android:layout_width="300dp"
android:layout_height="300dp">
<ImageView
android:id="#+id/mainContentImage"
android:layout_width="300dp"
android:layout_height="300dp"/>
<LinearLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#drawable/shape_circle">
</LinearLayout>
</FrameLayout>
here is the shape_circle.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/shape_circle_rect"/>
<item android:drawable="#drawable/shape_circle_oval"/>
</layer-list>
shape_circle_rect.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<padding
android:left="-70dp"
android:top="-70dp"
android:right="-70dp"
android:bottom="-70dp"/>
</shape>
shape_circle_oval.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<stroke android:color="#ffffff" android:width="70dp"/>
</shape>
its not exactly what you searching for but it could help.
hope this is woking........read abount styles and other part of developers
may help you
http://developer.android.com/reference/android/R.style.html

Categories

Resources