Reputation: 1148
How can I provide a border with attached type for a Linear layout in Android. I am developing a Xamarin Android application.
I have given following code to achieve rounded corners for Layout.
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp"/>
<padding android:left="10dp"
android:right="10dp"
android:top="10dp"
android:bottom="10dp"/>
<stroke android:width="1dp"
android:color="#CCCCCC"/> </shape>
Upvotes: 1
Views: 176
Reputation: 14956
as Seyed Masood Khademi said,you could use Nine Patch Image to achive the effect easily,ofcourse you could also do this with custom view.here is a simple sample:
create a custom view:
public class BubbleLayout : FrameLayout
{
public static int LEFT = 1;
public static int TOP = 2;
public static int RIGHT = 3;
public static int BOTTOM = 4;
// radius size
private int mRadius;
//the center of the base of a triangle
private Point mDatumPoint;
//Triangle position offset (centered by default)
private int mOffset;
private Paint mBorderPaint;
private Path mPath;
private RectF mRect;
//Direction of triangle
private int mDirection;
protected BubbleLayout(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public BubbleLayout(Context context) : base(context)
{
init(context,null);
}
private void init(Context context, IAttributeSet attrs)
{
TypedArray ta = context.ObtainStyledAttributes(attrs, Resource.Styleable.BubbleLayout);
//back ground color
var backGroundColor = ta.GetColor(Resource.Styleable.BubbleLayout_background_color, Color.White);
//shadow color
var shadowColor = ta.GetColor(Resource.Styleable.BubbleLayout_shadow_color,
Color.ParseColor("#999999"));
int defShadowSize = (int)TypedValue.ApplyDimension(ComplexUnitType.Px,
4, Resources.DisplayMetrics);
//shadow size
int shadowSize = ta.GetDimensionPixelSize(Resource.Styleable.BubbleLayout_shadow_size, defShadowSize);
mRadius = ta.GetDimensionPixelSize(Resource.Styleable.BubbleLayout_radius, 0);
//Triangular direction
mDirection = ta.GetInt(Resource.Styleable.BubbleLayout_direction, BOTTOM);
mOffset = ta.GetDimensionPixelOffset(Resource.Styleable.BubbleLayout_offset, 0);
ta.Recycle();
mBorderPaint = new Paint();
mBorderPaint.AntiAlias = true;
mBorderPaint.Color = backGroundColor;
mBorderPaint.SetShadowLayer(shadowSize, 0, 0, shadowColor);
mPath = new Path();
mRect = new RectF();
mDatumPoint = new Point();
SetWillNotDraw(false);
//Turn off hardware acceleration
SetLayerType(LayerType.Software, null);
}
public BubbleLayout(Context context, IAttributeSet attrs) : base(context, attrs)
{
init(context, attrs); ;
}
public BubbleLayout(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
init(context, attrs);
}
private void drawLeftTriangle(Canvas canvas)
{
int triangularLength = PaddingLeft;
if (triangularLength == 0)
{
return;
}
mPath.AddRoundRect(mRect, mRadius, mRadius, Path.Direction.Ccw);
mPath.MoveTo(mDatumPoint.X, mDatumPoint.Y - triangularLength / 2);
mPath.LineTo(mDatumPoint.X - triangularLength / 2, mDatumPoint.Y);
mPath.LineTo(mDatumPoint.X, mDatumPoint.Y + triangularLength / 2);
mPath.Close();
canvas.DrawPath(mPath, mBorderPaint);
}
private void drawTopTriangle(Canvas canvas)
{
int triangularLength = PaddingTop;
if (triangularLength == 0)
{
return;
}
mPath.AddRoundRect(mRect, mRadius, mRadius, Path.Direction.Ccw);
mPath.MoveTo(mDatumPoint.X + triangularLength / 2, mDatumPoint.Y);
mPath.LineTo(mDatumPoint.X, mDatumPoint.Y - triangularLength / 2);
mPath.LineTo(mDatumPoint.X - triangularLength / 2, mDatumPoint.Y);
mPath.Close();
canvas.DrawPath(mPath, mBorderPaint);
}
private void drawRightTriangle(Canvas canvas)
{
int triangularLength = PaddingRight;
if (triangularLength == 0)
{
return;
}
mPath.AddRoundRect(mRect, mRadius, mRadius, Path.Direction.Ccw);
mPath.MoveTo(mDatumPoint.X, mDatumPoint.Y - triangularLength / 2);
mPath.LineTo(mDatumPoint.X + triangularLength / 2, mDatumPoint.Y);
mPath.LineTo(mDatumPoint.X, mDatumPoint.Y + triangularLength / 2);
mPath.Close();
canvas.DrawPath(mPath, mBorderPaint);
}
private void drawBottomTriangle(Canvas canvas)
{
int triangularLength = PaddingBottom;
if (triangularLength == 0)
{
return;
}
mPath.AddRoundRect(mRect, mRadius, mRadius, Path.Direction.Ccw);
mPath.MoveTo(mDatumPoint.X + triangularLength / 2, mDatumPoint.Y);
mPath.LineTo(mDatumPoint.X, mDatumPoint.Y + triangularLength / 2);
mPath.LineTo(mDatumPoint.X - triangularLength / 2, mDatumPoint.Y);
mPath.Close();
canvas.DrawPath(mPath, mBorderPaint);
}
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
if (mDatumPoint.X > 0 && mDatumPoint.Y > 0)
switch (mDirection)
{
case 1:
drawLeftTriangle(canvas);
break;
case 2:
drawTopTriangle(canvas);
break;
case 3:
drawRightTriangle(canvas);
break;
case 4:
drawBottomTriangle(canvas);
break;
}
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
base.OnSizeChanged(w, h, oldw, oldh);
mRect.Left = PaddingLeft;
mRect.Top = PaddingTop;
mRect.Right = w - PaddingRight;
mRect.Bottom = h - PaddingBottom;
switch (mDirection)
{
case 1:
mDatumPoint.X = PaddingLeft;
mDatumPoint.Y = h / 2;
break;
case 2:
mDatumPoint.X = w / 2;
mDatumPoint.Y = PaddingTop;
break;
case 3:
mDatumPoint.X = w - PaddingRight;
mDatumPoint.Y = h / 2;
break;
case 4:
mDatumPoint.X = w / 2;
mDatumPoint.Y = h - PaddingBottom;
break;
}
if (mOffset != 0)
{
applyOffset();
}
}
/**
* Set the triangle offset position
*
* @param offset
*/
public void setTriangleOffset(int offset)
{
this.mOffset = offset;
applyOffset();
Invalidate();
}
private void applyOffset()
{
switch (mDirection)
{
case 1:
case 2:
mDatumPoint.Y += mOffset;
break;
case 3:
case 4:
mDatumPoint.X += mOffset;
break;
}
}
}
define a attrs.xml
in Resources/values:
<declare-styleable name="BubbleLayout">
<attr name="background_color" format="color" />
<attr name="shadow_color" format="color" />
<attr name="shadow_size" format="dimension" />
<attr name="radius" format="dimension" />
<attr name="direction" format="enum">
<enum name="left" value="1" />
<enum name="top" value="2" />
<enum name="right" value="3" />
<enum name="bottom" value="4" />
</attr>
<attr name="offset" format="dimension" />
in your layout.xaml:
<namespace.BubbleLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp" //You must set enough padding to draw the triangle and shadow
app:background_color="#FF4081"
app:direction="bottom"
app:offset="-20dp"
app:radius="4dp"
app:shadow_color="#999999"
app:shadow_size="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HelloWorld"
/>
</namespace.BubbleLayout>
Upvotes: 0
Reputation: 173
You must use Android Nine Patch Image. Nine patch image is an android special image format which can make the background image scaled correctly.
Upvotes: 1