I have a simple class, BoundedView that extends View. I'm doing this primarily to mess with the onTouchEvent callback function.
Is there a way to draw a border around each instance of this view, from the class itself? If not, what is the easiest way to implement this?
Implementation:
public class BoundedView extends View
{
public String cellName = "no name";
// constructors are here.
#Override
public void onDraw( Canvas canvas )
{
// maybe here? Right now it's invisible, used only for touch detection
}
#Override
public boolean onTouchEvent( MotionEvent event )
{
Intent i = new Intent( getContext(), TabCellDetails.class );
i.putExtra( "cellName", this.cellName );
getContext().startActivity( i );
return false;
}
}
Using:
<com.lifecoderdev.android.drawing1.BoundedView
android:id="#+id/boundedView1"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="78dp"
android:layout_marginRight="96dp"
android:tag="Smooth Endoplasmic Reticulum"/>
EDIT: This gets me close:
public void onDraw( Canvas canvas )
{
int[] colors = { 0xFF000000, 0xCC000000 };
float[] radii = { 5, 5, 5, 5, 5, 5, 5, 5 };
GradientDrawable drawable = new GradientDrawable( GradientDrawable.Orientation.TOP_BOTTOM, colors );
drawable.setCornerRadii( radii );
drawable.setStroke( 1, 0xFF000000 );
this.setBackgroundDrawable( drawable );
}
However, it is drawing a fully filled in black box, not a transparent one with a black border.
EDIT 2: Got it:
Paint paint = new Paint();
paint.setColor( Color.RED );
paint.setStrokeWidth( 1.0f );
canvas.drawRect( 0, 0, getWidth(), 1.0f, paint );
canvas.drawRect( 0, 0, 1.0f, getHeight(), paint );
canvas.drawRect( 0, getHeight()-1.0f, getWidth(), getHeight(), paint );
canvas.drawRect( getWidth()-1.0f, 0, getHeight(), getWidth(), paint );
EDIT 3: Andreas and Warren's solution was much nicer:
#Override
public void onDraw( Canvas canvas )
{
Paint paint = new Paint();
paint.setColor( Color.RED );
paint.setStrokeWidth( 1.5f );
paint.setStyle( Style.STROKE );
canvas.drawRect( 0, 0, getWidth(), getHeight(), paint );
}
Yes inside your onDraw() is the right place.
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
That should work. If you set the paint variable correctly (stroke width, color) you should see your border.
Related
I'm new to Android and I want to draw points on top of my view using a canvas, but when my OnDrawListener is hit, nothing is drawn on my view and I can't figure out why.
new OnDrawListener() {
#Override
public void onLayerDrawn(Canvas canvas, float pageWidth, float pageHeight, int displayedPage) {
canvas.drawPoint(pageHeight /2, pageHeight /2, paint);
view.draw(canvas);
}
}
Here's how I setup my paint :
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(3);
Thank you.
UPDATE :
Here you can find my full class :
https://pastebin.com/ehB5NamS
I'd like to draw a Bitmap on a Canvas, with a (linear) alpha gradient applied. The important point is that I don't want to overlay the image with any other color; the background (coming from the Views behind the View that I'd be drawing this Canvas to) should just "shine through". To illustrate, my goal would be something like this (the checkerboard pattern represents the View behind)
One would think that I could do something like this:
Bitmap bitmap = ...;
Paint paint = new Paint();
paint.setShader(new LinearGradient(0, 0, 100, 0, FROM, TO, Shader.TileMode.CLAMP));
canvas.drawBitmap(bitmap, 0, 0, paint);
but LinearGradient's FROM and TO arguments here would need to be colors, not alpha values; so there's no way that I see to specify that e.g. FROM should be fully transparent and TO should be fully opaque (without applying any color overlay).
use a ComposeShader, like this:
class V extends View {
Bitmap bitmap;
Paint paint = new Paint();
public V(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.chrome);
Shader shaderA = new LinearGradient(0, 0, bitmap.getWidth(), 0, 0xffffffff, 0x00ffffff, Shader.TileMode.CLAMP);
Shader shaderB = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SRC_IN));
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), paint);
}
}
Based on this answer about masking, I was able to do this using a secondary off-screen canvas:
Bitmap backing = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
{
Canvas offscreen = new Canvas(backing);
offscreen.drawBitmap(bitmap, 0, 0, null);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
paint.setShader(new LinearGradient(0, 0, 100, 0, 0x00000000, 0xFF000000, Shader.TileMode.CLAMP));
offscreen.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), paint);
}
canvas.drawBitmap(backing, 0, 0, null);
I have this code, which draws a circular image of the artist currently playing in my android app.
package com.myradio.aacplay;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class ImageViewRounded extends ImageView {
public ImageViewRounded(Context context) {
super(context);
}
public ImageViewRounded(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ImageViewRounded(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
BitmapDrawable drawable = (BitmapDrawable) getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap fullSizeBitmap = drawable.getBitmap();
int scaledWidth = getMeasuredWidth();
int scaledHeight = getMeasuredHeight();
Bitmap mScaledBitmap;
if (scaledWidth == fullSizeBitmap.getWidth()
&& scaledHeight == fullSizeBitmap.getHeight()) {
mScaledBitmap = fullSizeBitmap;
} else {
mScaledBitmap = Bitmap.createScaledBitmap(fullSizeBitmap,
scaledWidth, scaledHeight, true /* filter */);
}
// Bitmap roundBitmap = getRoundedCornerBitmap(mScaledBitmap);
// Bitmap roundBitmap = getRoundedCornerBitmap(getContext(),
// mScaledBitmap, 10, scaledWidth, scaledHeight, false, false,
// false, false);
// canvas.drawBitmap(roundBitmap, 0, 0, null);
Bitmap circleBitmap = getCircledBitmap(mScaledBitmap);
canvas.drawBitmap(circleBitmap, 0, 0, null);
}
public Bitmap getRoundedCornerBitmap(Context context, Bitmap input,
int pixels, int w, int h, boolean squareTL, boolean squareTR,
boolean squareBL, boolean squareBR) {
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final float densityMultiplier = context.getResources()
.getDisplayMetrics().density;
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, w, h);
final RectF rectF = new RectF(rect);
// make sure that our rounded corner is scaled appropriately
final float roundPx = pixels * densityMultiplier;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
// draw rectangles over the corners we want to be square
if (squareTL) {
canvas.drawRect(0, 0, w / 2, h / 2, paint);
}
if (squareTR) {
canvas.drawRect(w / 2, 0, w, h / 2, paint);
}
if (squareBL) {
canvas.drawRect(0, h / 2, w / 2, h, paint);
}
if (squareBR) {
canvas.drawRect(w / 2, h / 2, w, h, paint);
}
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(input, 0, 0, paint);
return output;
}
Bitmap getCircledBitmap(Bitmap bitmap) {
Bitmap result = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
int color = Color.BLUE;
Paint paint = new Paint();
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
// canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, bitmap.getHeight()/2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return result;
}
}
and my xml view code:
<com.radio.myradio.ImageViewRounded
android:id="#+id/imagine"
android:src="#drawable/zupi"
android:layout_width="280dp"
android:layout_height="265dp"
android:layout_gravity="center"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:gravity="center"
android:visibility="gone"/>
It works fine, but my problem is that i can't/don't know how to add a white border to the circular view.
You can try using this CircularImageView I made. It's easy to use and supports custom borders.
Dude here is the solution..
https://github.com/MostafaGazar/CustomShapeImageView
For more detail
https://coderwall.com/p/hmzf4w
Use this library u will find the circular shape in this library and also easy use.
U can also make your custom shape to this library like cloud etc.
this library supports SVG file format and they made the SVG file of Rounded corner Imageview.
Just use and let me know if there is any problem
I faced a similar problem with rounded image , i tried adding background to imageview and giving it padding but it didn't work , so i ended up using RoundedImageView. The usage is pretty simple and it works perfectly
Try to draw circle behinde your Bitmap?
#Override
protected void onDraw(Canvas canvas) {
canvas.drawCircle(0, 0, imageRadius+borderSize, paint);
BitmapDrawable drawable = (BitmapDrawable) getDrawable();
if (drawable == null) {
return;
}
...
I'm new in Android and I've written the following sample code.
public class Circle extends View {
Paint paint = new Paint();
Path path = new Path();
private static final String s = "Hello world example";
public Circle(Context context) {
super(context);
paint.setColor(Color.BLACK);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2);
paint.setAntiAlias(true);
paint.setTextSize(30);
}
public void onDraw(Canvas c) {
path.addCircle(getWidth()/2, getHeight()/2, 180, Direction.CW);
c.drawTextOnPath(s, path, 0, 10, paint);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
The Canvas.drawTextOnPath() is displaying the the text beginning from the right side (I mean positive X-axis). I want to display the text from top in a clock-wise. I want to change the starting position of the text. I'm confused about Android Canvas.translate() and Canvas.scale(). Or should I use Canvas.rotate()? I've pasted the output below for clear understanding my question.
I want to display the output in this form.
I've finally fixed my Canvas issue by adding the Canvas.rotate(float degrees, float px, float py) in my code before applying and Canvas methods. Below is the code.
public class Circle extends View {
Paint paint = new Paint();
Path path = new Path();
private static final String s = "Hello world example";
public Circle(Context context) {
super(context);
paint.setColor(Color.BLACK);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2);
paint.setAntiAlias(true);
paint.setTextSize(30);
}
public void onDraw(Canvas c) {
c.rotate(-90, getWidth()/2, getHeight()/2);
path.addCircle(getWidth()/2, getHeight()/2, 180, Direction.CW);
c.drawTextOnPath(s, path, 0, 10, paint);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
I tried Canvas.rotate(float degrees) before but didn't worked. However, Canvas.rotate(float degrees, float px, float py) worked!
Instead of circle, arc can be used:
Path path = new Path();
RectF rect = new RectF(width/2 - radius, height/2 - radius, width/2 + radius, height/2 + radius);
path.addArc(rect 270, 270);
canvas.drawTextOnPath(msg., path, 0, 0, paint);
The path can be translated, rotated and scaled by using Matrix.
For example, the above code will draw the text starting from the first quadrant, i.e, from (y, 0). To start the drawing from (-y, 0) in clockwise direction,
Path path = new Path();
RectF rect = new RectF(width/2 - radius, height/2 - radius, width/2 + radius, height/2 + radius);
Matrix matrix = new Matrix();
matrix.setScale(-1, -1, width/2, height/2);
path.addArc(rect, 270, 270);
path.transform(matrix);
canvas.drawTextOnPath(msg, path, 0, 0, paint);
I have a canvas drawing, I am going to use onTouch to change the colour of the drawing. It is a house, and on touching the screen once it will change to a darker shade. I have only been told that I will need to move the method calls into dayTime and nightTime, switchable by boolean, and that the text daytime and night time has to be rendered on the image accordingly.
Below is the code I used to draw the image. Any help on how to finish this would be appreciated:
/*
* DrawView.java
*/
public class DrawView extends View implements OnTouchListener
{
private Paint backgroundPaint = new Paint();
private Paint drawPaint_grass = new Paint();
private Paint drawPaint_door = new Paint();
private Paint drawPaint_house = new Paint();
private Paint drawPaint_roof = new Paint();
private Paint circlePaint = new Paint();
private Paint circlePaint_sun = new Paint();
private Paint textPaint = new Paint();
private Paint path = new Paint();
private Path trianglePath;
private float sx, sy;
public DrawView(Context context)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
backgroundPaint.setColor(Color.rgb(135,250,205));
backgroundPaint.setAntiAlias(true);
backgroundPaint.setStyle(Style.FILL);
drawPaint_grass.setColor(Color.rgb(124, 252, 0));
drawPaint_grass.setStyle(Style.FILL);
drawPaint_door.setColor(Color.RED);
drawPaint_door.setStyle(Style.FILL);
//drawPaint_.setColor(Color.RED);
//drawPaint_door.setStyle(Style.FILL);
drawPaint_house.setColor(Color.rgb(205, 133, 63));
drawPaint_house.setStyle(Style.FILL);
drawPaint_roof.setColor(Color.rgb(160, 82, 45));
drawPaint_roof.setStyle(Style.FILL);
circlePaint_sun.setColor(Color.rgb(255, 255, 0));
circlePaint_sun.setStyle(Style.FILL);
trianglePath = new Path();
trianglePath.moveTo(70, 300); // starting point
trianglePath.lineTo(170,250); // 1st vertix
trianglePath.lineTo(270, 300); // 2nd vertix
trianglePath.lineTo(70, 300); // 3rd vertix and close
//path.moveTo(getRight()/2, getLeft()/2, getTop()/2, getBottom()/2);
textPaint.setColor(Color.BLACK);
textPaint.setStyle(Style.FILL);
//255, 255, 240
circlePaint.setColor(Color.rgb(211, 211, 211));
circlePaint.setStyle(Style.FILL);
this.setOnTouchListener(this);
}
#Override
public void onDraw(Canvas canvas)
{
//canvas.drawPath(path, paint);
//canvas.drawPath(path, paint);
// Draw white background
canvas.drawRect(this.getLeft(), this.getTop(), this.getRight(), this.getBottom(), backgroundPaint);
//draw a rectangle with blue paint
canvas.drawRect(0,400, 540,600, drawPaint_grass);
canvas.drawRect(100,400, 240,300, drawPaint_house);
canvas.drawRect(150,400, 190,335, drawPaint_door);
canvas.drawPath(trianglePath, drawPaint_roof);
//draw text with green paint
canvas.drawText("Muhibur Rahim", 232, 565, textPaint);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(sx-30,sy-30, 3, circlePaint);
canvas.drawCircle(80, 80, 30, circlePaint_sun);
}
public boolean onTouch(View v, MotionEvent event)
{
//update the coordinates for the OnDraw method above, with wherever we touch
sx = event.getX();
sy = event.getY();
invalidate();
return true;
}
}
I was thinking of putting the colouring part of code (circlePaint_sun.setColor(Color.rgb(255, 255, 0)) into methods (eg. static void dayTime() under private Drawview(Context, Context), and then assigning the two methods values 0 and 1, and on touch or click (i think onclick would be better) a counter increases and the values alternate between 0 and 1. However I am not sure how to use that in a code after repeated tries, any help is appreciated...
Add a private boolean dark = false; to your variables.
In your onDraw method, add something like
if (dark) backgroundPaint.setColor(Color.rgb(0,0,0));
else backgroundPaint.setColor(Color.rgb(255,255,255));
before you draw your background.
Change your boolean inside the onTouch method:
if (event.getAction() == MotionEvent.ACTION_DOWN) {
dark = !dark;
DrawView();
}