I'm using this code to draw a half in my app:
<?xml version="1.0" encoding="utf-8" ?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item
android:left="35dp"
android:top="40dp"
android:bottom="40dp"
android:right="0dp">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" android:innerRadius="30dp" android:thickness="0dp">
<solid android:color="#color/transparent"/>
<stroke android:width="3dp" android:color="#color/White"/>
</shape>
</item>
</layer-list>
output :
but i need something like below :
how to draw this ?
I would suggest to draw it through code.
1- Create class MyView and put below code.
public class MyView extends View {
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
float width = (float) getWidth();
float height = (float) getHeight();
float radius;
if (width > height) {
radius = height / 4;
} else {
radius = width / 4;
}
Path path = new Path();
path.addCircle(width / 2,
height / 2, radius,
Path.Direction.CW);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.FILL);
float center_x, center_y;
final RectF oval = new RectF();
paint.setStyle(Paint.Style.STROKE);
center_x = width / 2;
center_y = height / 2;
oval.set(center_x - radius,
center_y - radius,
center_x + radius,
center_y + radius);
canvas.drawArc(oval, 90, 180, false, paint);
}
}
2-Initialize this class inside you activity or fragment:-
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
Your can use a rectangle shape .xml file and edit the corners on one side only.
Example:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:height="30dp"
android:width="30dp"/>
<solid android:color="#color/black"/>
<corners android:topLeftRadius="15dp"
android:bottomLeftRadius="15dp"/>
</shape>
You can use <clip /> drawable in order to cut-off part of your circle.
http://developer.android.com/guide/topics/resources/drawable-resource.html#Clip
this is how i created my semi circle in a drawable xml file.
<size
android:width="180dp"
android:height="90dp"></size>
<corners
android:topLeftRadius="200dp"
android:topRightRadius="200dp"></corners>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="180dp"
android:height="90dp"></size>
<corners
android:topLeftRadius="200dp"
android:topRightRadius="200dp"></corners>
<stroke android:width="5px" android:color="#color/black" />
</shape>
Related
I would like to create rectangle drawable then rotate it so top right side appear slanted, i would eventually overlay over rounded corner image ,in effort to create a copy of the image below , using some drawable
am hoping for using with xml , but it just slanted and edge never touch other side
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item >
<rotate
android:fromDegrees="19.5"
android:toDegrees="-19.5"
android:pivotX="-50%"
android:pivotY="0%"
>
<shape
android:shape="rectangle" >
<solid
android:color="#android:color/black" />
</shape>
</rotate>
</item>
create a custom Drawable that draws the shape: but again i fail , would love any help ? thank you
#Override
public void draw(Canvas canvas) {
int width = this.getBounds().width();
int height = this.getBounds().height();
double angle = 19.5 * (Math.PI / 180.0);
double offsetX = height * Math.tan(angle);
Path path = new Path();
Paint paint = new Paint();
path.moveTo(0, 0);
path.lineTo(width, 0);
path.lineTo(width, height);
path.lineTo((int)offsetX, height);
path.close();
paint.setColor(_color);
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(path, paint);
}
I would like to scale a rectangle drawable downwards, then rotate it so once it is clipped by the view it resembles a trapezoid with the left side slanted:
The rotation is working fine:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item >
<rotate
android:fromDegrees="-19.5"
android:toDegrees="-19.5"
android:pivotX="0%"
android:pivotY="0%"
>
<shape
android:shape="rectangle" >
<solid
android:color="#android:color/black" />
</shape>
</rotate>
</item>
</layer-list>
However to prevent a big gap where the rectangle has rotated away from the bottom of the view I want to scale vertically by 200% before the rotation happens. I was hoping that I could do something like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item >
<scale
android:scaleWidth="100%"
android:scaleHeight="200%"
android:scaleGravity="top"
>
<rotate
android:fromDegrees="-19.5"
android:toDegrees="-19.5"
android:pivotX="0%"
android:pivotY="0%"
>
<shape
android:shape="rectangle" >
<solid
android:color="#android:color/black" />
</shape>
</rotate>
</scale>
</item>
</layer-list>
but this just causes the rectangle to disappear. Does anyone know how best to achieve this?
No really a true answer but I solution that I am using now is to create a custom Drawable that draws the shape:
public void setColor(int color) {
_color = color;
}
#Override
public void draw(Canvas canvas) {
int width = this.getBounds().width();
int height = this.getBounds().height();
double angle = 19.5 * (Math.PI / 180.0);
double offsetX = height * Math.tan(angle);
Path path = new Path();
Paint paint = new Paint();
path.moveTo(0, 0);
path.lineTo(width, 0);
path.lineTo(width, height);
path.lineTo((int)offsetX, height);
path.close();
paint.setColor(_color);
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(path, paint);
}
This does the job for now, although it is frustrating that I cannot find a way to do this in the xml.
Aim: Stroke only the top and bottom.
What I've tried:
Below is a copy of my XML.
I've tried following the solution in This Stack Overflow Answer.
But my problem is that the doesn't let me choose the options of cutting off the left and right by 1dp as per the solution.
Any ideas?
Code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape >
<gradient
android:startColor="#color/secondaryButtonStartColorSelected"
android:endColor="#color/secondaryButtonEndColorSelected"
android:angle="270" />
<stroke
android:width="#dimen/secondary_button_border_size"
android:color="#color/secondaryButtonBorderColorSelected" />
</shape>
</item>
<item android:state_focused="true" >
<shape>
<gradient
android:startColor="#color/secondaryButtonStartColorSelected"
android:endColor="#color/secondaryButtonEndColorSelected"
android:angle="270" />
<stroke
android:width="#dimen/secondary_button_border_size"
android:color="#color/secondaryButtonBorderColorSelected"/>
</shape>
</item>
</selector>
You could create a custom Drawable to handle this for you, but you'd have to set it in code vs XML. Here's a quick and dirty version:
public class HorizontalStrokeDrawable extends Drawable {
private Paint mPaint = new Paint();
private int mStrokeWidth;
public HorizontalStrokeDrawable (int strokeColor, int strokeWidth) {
mPaint.setColor(strokeColor);
mStrokeWidth = strokeWidth;
}
#Override
public void draw (Canvas canvas) {
Rect bounds = getBounds();
canvas.drawRect(0, 0, bounds.right, mStrokeWidth, mPaint);
canvas.drawRect(0, bounds.bottom - mStrokeWidth, bounds.right, bounds.bottom, mPaint);
}
#Override
public void setAlpha (int alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
#Override
public void setColorFilter (ColorFilter cf) {
mPaint.setColorFilter(cf);
invalidateSelf();
}
#Override
public int getOpacity () {
return PixelFormat.TRANSLUCENT;
}
}
Now you can just set it wherever you need it:
view.setBackgroundDrawable(new HorizontalStrokeDrawable(myColor, myStrokeWidth));
I'd like to create a rectangle shape with two solid colors (horizontally) to achieve something like this:
I heard about layer-list, i though i could use it to contains two rectangle with a different color but it seems that it only lays shapes vertically.
Is there a way to achieve this using lalyer-list or should i use something totally different? I'd like to keep it simple with ability to change the shape colors at runtime.
Thanks.
this will surely draw the shape as per your Requirement :
Adjust size of <item> as you need !
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="50dip">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#0000FF" />
</shape>
</item>
<item android:right="50dip">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#ff0000" />
</shape>
</item>
</layer-list>
You can create custom drawable for this. Just extend Drawable class.
Here is a sample code which draws a rectangle like you wanted, you can provide any number of colors.
public class ColorBarDrawable extends Drawable {
private int[] themeColors;
public ColorBarDrawable(int[] themeColors) {
this.themeColors = themeColors;
}
#Override
public void draw(Canvas canvas) {
// get drawable dimensions
Rect bounds = getBounds();
int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top;
// draw background gradient
Paint backgroundPaint = new Paint();
int barWidth = width / themeColors.length;
int barWidthRemainder = width % themeColors.length;
for (int i = 0; i < themeColors.length; i++) {
backgroundPaint.setColor(themeColors[i]);
canvas.drawRect(i * barWidth, 0, (i + 1) * barWidth, height, backgroundPaint);
}
// draw remainder, if exists
if (barWidthRemainder > 0) {
canvas.drawRect(themeColors.length * barWidth, 0, themeColors.length * barWidth + barWidthRemainder, height, backgroundPaint);
}
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter cf) {
}
#Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
}
This will give you two colors half and half vertically. Put this code in a drawable resource.
<item
android:top="320dip">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#color/red" />
</shape>
</item>
<item android:bottom="320dip">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#color/yellow" />
</shape>
</item>
I am new to Android. Now I have a problem about drawing borders on LinearLayout. I draw borders by following codes.
public class Borders{
int w;
int h;
public Borders(int x, int y){
w = x;
h = y;
}
public void drawBorderInImg(Canvas canvas){
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(10);
paint.setColor(Color.BLACK);
canvas.drawLine(0, 0, w, 0, paint);
canvas.drawLine(w, 0, w, h, paint);
canvas.drawLine(w, h, 0, h, paint);
canvas.drawLine(0, h, 0, 0, paint);
}
}
I create a boolean value and use onclickListener() to control it. By default, the value is false, so there is no border on the screen.
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
// operate.refresh(ShapeData.figureList1);
Borders borders = new Borders(img01.getWidth(), img01.getHeight());
if(img01DrawOrNot){
borders.drawBorderInImg(canvas);
}
And then I do
img01.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(img01DrawOrNot){
img01DrawOrNot = false;
} else{
img01DrawOrNot = true;
}
}
});
I set android:clickable=true in xml. It actually works. But, I need to postInvalidate() it. In fact, I can't refresh it because it contains some random shapes, when I do postInvalidate(), all views will change. How can it change automatically? So when I click, it will appear and when I click again, it will disappear. Could someone help me? Cheers!
if you like, try this.
(create this layout in your drawable folder)
layout_border.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<stroke android:width="2dp" android:height="2dp"
android:color="#FF0000" />
<solid android:color="#000000" />
<padding android:left="1dp" android:top="1dp" android:right="1dp"
android:bottom="1dp" />
<corners android:radius="1dp" android:bottomRightRadius="5dp"
android:bottomLeftRadius="0dp" android:topLeftRadius="5dp"
android:topRightRadius="0dp" />
</shape>
</item>
</layer-list>
main.xml
<?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:background="#ffffff"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
/>
<LinearLayout android:layout_gravity="center"
android:layout_width="200dp" android:layout_height="200dp" android:background="#drawable/layout_border" />
</LinearLayout>