I´m trying to display a moving cloud over a blue sky. The blue background is displayed but the cloud doesn't appear. I've tried the different approaches in other questions here but nothing works. My code is:
public class CloudBackground extends View {
Bitmap cloud;
int x = 0;
int y = 0;
Paint paint = new Paint();
Rect rectangle = new Rect(0,0,100,100);
public CloudBackground(Context context,AttributeSet attrs) {
super(context,attrs);
cloud = BitmapFactory.decodeResource(getResources(),R.drawable.cloud1);
}
#Override
protected void onDraw (Canvas canvas){
super.onDraw(canvas);
Rect back = new Rect();
back.set(0,0,canvas.getWidth(), canvas.getHeight());
Paint pBlue = new Paint();
pBlue.setStyle(Paint.Style.FILL);
pBlue.setColor(Color.CYAN);
canvas.drawRect(back, pBlue);
drawCloud(x,y,canvas);
if (x < canvas.getWidth())
x = x + 10;
else {
y = y + 10;
x = 0;
}
invalidate();
}
private void drawCloud(int x2, int y2, Canvas canvas) {
canvas.drawBitmap(cloud, x2, y2,paint);
}
Ok. Try this:
public CloudBackground(Context context,AttributeSet attrs) {
super(context,attrs);
cloud = BitmapFactory.decodeResource(context.getApplicationContext().getResources(),R.drawable.cloud1);
}
The issue was finally solved using a.jpg instead a .png. As simple as that and with no reason.
Related
I know how to move the image in circle in android while using this source codeMove image in circle
This code is perfect in moving imageview in circle but i want to move aeroplane picture in circle and i want that it should be look like real motion of airplane. Can any one help me
public class AnimationView extends View {
Paint paint;
Bitmap bm;
int bm_offsetX, bm_offsetY;
Path animPath;
PathMeasure pathMeasure;
float pathLength;
float step; //distance each step
float distance; //distance moved
float[] pos;
float[] tan;
Matrix matrix;
public AnimationView(Context context) {
super(context);
initMyView();
}
public AnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
initMyView();
}
public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initMyView();
}
public void initMyView(){
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(4);
paint.setStyle(Paint.Style.STROKE);
DashPathEffect dashPath = new DashPathEffect(new float[]{6,6}, (float)2.0);
paint.setPathEffect(dashPath);
bm = BitmapFactory.decodeResource(getResources(), R.drawable.airplane);
bm_offsetX = bm.getWidth()/2;
bm_offsetY = bm.getHeight()/2;
animPath = new Path();
animPath.addCircle(600, 600, 500, Path.Direction.CW);
animPath.close();
pathMeasure = new PathMeasure(animPath, false);
pathLength = pathMeasure.getLength();
step = 1;
distance = 0;
pos = new float[2];
tan = new float[2];
matrix = new Matrix();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(animPath, paint);
if(distance < pathLength){
pathMeasure.getPosTan(distance, pos, tan);
matrix.reset();
float degrees = (float)(Math.atan2(tan[0], tan[1])*0.0/Math.PI);
matrix.postRotate(degrees, bm_offsetX, bm_offsetY);
matrix.postTranslate(pos[0]-bm_offsetX, pos[1]-bm_offsetY);
canvas.drawBitmap(bm, matrix, null);
distance += step;
}else{
distance = 0;
}
invalidate();
}
I am working on an application similar to Amaziograph of iPhone also known as kaleidoscope or mandala.
Till now I have tried and have made one particular layout of that app
I have extended the canvas and have made a custom canvas, where I have divided canvas in 9 parts similar to image and in draw method I have rotated the canvas and copied its content in for loop. Here is my canvas class code for above circular division shape
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.madala.mandaladrawing.R;
import com.madala.mandaladrawing.model.DrawingEvent;
import com.madala.mandaladrawing.utils.Common;
public class CanvasView extends View {
private final Context context;
private Bitmap bitmap;
private Canvas bitmapCanvas;
private Paint bitmapPaint;
private Path path = new Path();
private Paint brushPaint;
private int numberOfMirror = 5;
private int cx, cy;
public CanvasView(Context context) {
super(context);
this.context = context;
init();
}
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
private void init() {
brushPaint = createPaint();
brushPaint.setColor(0xffffffff);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
canvas.drawPath(path, brushPaint);
for (int i = 1; i < numberOfMirror; i++) {
canvas.rotate(360f / numberOfMirror, cx, cy);
canvas.drawPath(path, brushPaint);
}
}
public void clearCanvas(){
bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setLayerType(View.LAYER_TYPE_HARDWARE, null);
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
bitmapPaint = new Paint(Paint.DITHER_FLAG);
cx = w / 2;
cy = h / 2;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
path.lineTo(x, y);
drawToCanvas(path, brushPaint);
path.reset();
break;
default:
return false;
}
invalidate();
return true;
}
private void drawToCanvas(Path path, Paint brushPaint) {
bitmapCanvas.drawPath(path, brushPaint);
for (int i = 1; i < numberOfMirror; i++) {
bitmapCanvas.rotate(360f / numberOfMirror, cx, cy);
bitmapCanvas.drawPath(path, brushPaint);
}
}
public int getCurrentBrushColor() {
return brushPaint.getColor();
}
public void setCurrentBrushColor(int color) {
brushPaint.setColor(color);
}
private Paint createPaint() {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setStrokeWidth(8f);
p.setStyle(Paint.Style.STROKE);
p.setStrokeJoin(Paint.Join.ROUND);
p.setStrokeCap(Paint.Cap.ROUND);
return p;
}
}
I am not able to achieve the functionality for below figure
I want to draw in one box and it should be copied in the other boxes. How could this be achieved a small guide will also be helpful?
Maybe you can save traces into array, and paste it to other drawing views
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//save initial x,y into array or send it to other canvas
/*public general variable*/
String Drawing +="[[x,y]";
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
//save middle x,y into array or send it to other canvas
String Drawing +=",[x,y]";
path.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
//save last point into array or send it to other canvas
String Drawing +=",[x,y]]";
path.lineTo(x, y);
drawToCanvas(path, brushPaint);
path.reset();
break;
default:
return false;
}
invalidate();
return true;
}
the string resultant should be all user traces
[[x,y],[x,y],[x,y],[x,y],[x,y]], trace 1
[[x,y],[x,y],[x,y],[x,y],[x,y]], trace 2
[[x,y],[x,y],[x,y],[x,y],[x,y]], trace 3
etc..
trace1 + trace2 +trace 3 = thing drawed by user.
when you want or maybe in real time, you can send the points drawed on this view to other view... or when users end writing send the string and extract the points...
Well it's just an idea, Hope i helped ;)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- this has changed from first answer -->
<dimen name="translation_size">30dp</dimen>
</resources>
...
int size = getResources().getDimensionPixelSize(R.dimen.translation_size);
...
private void drawToCanvas(Path path, Paint brushPaint) {
bitmapCanvas.drawPath(path, brushPaint); // just render normally
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, brushPaint);
int xMax = getWidth() / size;
int yMax = getHeight() / size;
int xMin = -xMax;
int yMin = -yMax;
for (int x = xMin; x <= xMax; x++) {
for (int y = yMin; y <= yMax; y++) {
if ((Math.abs(x % 6) == 0 && Math.abs(y % 4) == 0) ||
(Math.abs(x % 6) == 3 && Math.abs(y % 4) == 2)) {
int xs = x * size;
int ys = y * size;
canvas.translate(xs, ys);
canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
canvas.translate(-xs, -ys);
}
}
}
}
You don't have to use resources like I did, but if you hard-code a size into your app, make sure you multiply by the screen density to get the correct pixel offsets.
I'm working on a project that requires me to draw a circle at a random location on the screen when the user touches the screen. When the touch event occurs it also needs to remove the last circle I drew, so that there can only be one circle on the screen at one time.
I have a class Circle, that I use to create a circle:
public class Circle extends View {
private final float x;
private final float y;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public Circle(Context context, float x, float y, int r) {
super(context);
mPaint.setColor(0x000000);
this.x = x;
this.y = y;
this.r = r;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.RED);
canvas.drawCircle(x, y, r, mPaint);
}
}
This is the activity from which a new Circle is created. It will also monitor touch events. Right now it is drawing a circle in the upper left hand corner of the screen, but that code will need to be moved into the onTouch method. I will likely calculate the random number using Random.
public class FingerTappingActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_finger_tapping);
LinearLayout circle = (LinearLayout) findViewById(R.id.lt);
View circleView = new Circle(this, 300, 300, 150);
circleView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
circle.addView(circleView);
circle.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
}
}
I have never worked with touch events before such as these and have no idea how to go about this. Some tips would be greatly appreciated.
Do some thing like this ,
public class DrawCircles extends View {
private float x = 100;
private float y = 100;
private int r = 50;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.RED);
canvas.drawCircle(x, y, r, mPaint);
}
public DrawCircles(Context context) {
super(context);
init();
}
public DrawCircles(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawCircles(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
void init() {
mPaint.setColor(0x000000);
// logic for random call here;
}
Random random = new Random();
void generateRandom() {
int minRadius = 100;
int w = getWidth();
int h = getHeight();
this.x = random.nextInt(w);
this.y = random.nextInt(h);
this.r = minRadius + random.nextInt(100);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
generateRandom();
invalidate();
return super.onTouchEvent(event);
}
}
This view will draw random circles inside the view . make some adjustments for generating x & y coordinates . add this view to xml then it will work.
I want to draw something like in android, to use it as a button. How to do that? any links or suggestion? Is it a bezier curve?
As stated in the comments, you can create a PNG and use it directly. If you want the sides to scale independently from the curve, you can 9-patch your image.
According to this post, you now have the option to define a path drawable in xml. But only for Lollipop and up.
Finally, you can create a base button and use the Path object to draw a quadratic curve. Example. I haven't tried it myself, but you should be able to fill the area below the bath Example 1, Example 2.
Edit:
I had a bit a time available to create an example of a Path implementation. In order to fill the section below the path, clipping needs to be used. This isn't an exact solution for you, but you should be able to get what you want by tweaking a few of the variables (x1, y1, x2, y2, x3, y3).
In my implementation I made use of a gradient instead of a solid colour, since it doesn't make a difference to the implementation, and it serves as a more general example.
public class PathView extends View
{
private Paint paintFill;
private Paint paintLine;
private Paint paintClear;
private Path path;
private int colour;
private float x0;
private float y0;
private float x1;
private float y1;
private float x2;
private float y2;
private float x3;
private float y3;
public PathView(Context context)
{
super(context);
}
public PathView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public PathView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
public PathView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
super.onLayout(changed, left, top, right, bottom);
initialize();
}
private void initialize()
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
{
// Path clipping uses hardware acceleration which is unavailable from 11 to 18
// https://stackoverflow.com/questions/8895677/work-around-canvas-clippath-that-is-not-supported-in-android-any-more
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
paintFill = new Paint();
paintFill.setAntiAlias(true);
LinearGradient gradient = new LinearGradient(0, getHeight(), 0, 0, Color.WHITE, colour, Shader.TileMode.CLAMP); // Vertical gradient
paintFill.setShader(gradient);
paintLine = new Paint();
paintLine.setColor(colour);
paintLine.setStrokeWidth(1.5f);
paintLine.setStrokeCap(Paint.Cap.ROUND);
paintLine.setStyle(Paint.Style.STROKE);
paintLine.setAntiAlias(true);
paintClear = new Paint();
paintClear.setColor(Color.WHITE);
paintClear.setAntiAlias(true);
}
public int getColour()
{
return colour;
}
public void setColour(int colour)
{
this.colour = colour;
initialize();
invalidate();
}
public void setVars(float x1, float y1, float x2, float y2)
{
// When the vars changes, the path needs to be updated.
// In order to make clipping easier, we draw lines from [x0, y0] to
// [x0, getHeight] and [x3, y3] to [x3, getHeight].
// This makes the fill section of the path everything below the path.
path = new Path();
float cx = getWidth() / 2;
float cy = getHeight() / 2;
this.x0 = 0;
this.y0 = cy + y1;
this.x1 = x1;
this.y1 = cy + y1;
this.x2 = x2;
this.y2 = cy + y2;
this.x3 = getWidth();
this.y3 = cy + y2;
// Move to bottom, draw up
path.moveTo(this.x0, getHeight());
path.lineTo(this.x0 - paintLine.getStrokeMiter(), this.y0);
path.cubicTo(this.x1, this.y1, this.x2, this.y2, this.x3, this.y3);
// Draw down
path.lineTo(this.x3 + paintLine.getStrokeMiter(), getHeight());
invalidate();
}
#Override
public void draw(Canvas canvas)
{
super.draw(canvas);
if (path != null && paintFill != null)
{
// Draw gradient background first, and then clip the irrelevant section away.
// This will let our gradient be uniform irrespective of the vars used.
canvas.drawRect(x0, 0, x3, getHeight(), paintFill);
canvas.save();
canvas.clipPath(path, Region.Op.DIFFERENCE);
canvas.drawRect(x0, 0, x3, getHeight(), paintClear);
canvas.restore();
canvas.drawPath(path, paintLine);
}
}
}
I want to add border for view, border width, color, radius can be set by user. So I try to draw a rect for it. When I use drawRoundRect to draw, the line at the corner is not smooth, it is thicker than the other places too. I don't know how to fix it. Please give me some instruction. Is there any other way to do it? I have to use code to draw it.
Thanks very much.
attached code: red corner of rect.
past code:
public class MPCTextView extends TextView {
// private Context context;
private final static String TAG = "MPCTextView";
public final static int DEFAULT_BACKGROUND_COLOR = Color
.parseColor("#28FF28");
public final static int DEFAULT_BORDER_COLOR = Color.parseColor("#FF0000");
public int mBoderWidth = 2;
public int mBoderColor;
public int mBoderRadius = 20;
public int mbackgroundColor;
public boolean isHaveBorder = true;
public boolean isHaveBackground = true;
RectF mRectF = new RectF();
Rect mRec = new Rect();
Paint mPaint = new Paint();
public MPCTextView(Context context) {
super(context);
// this.context = context;
}
#Override
protected void onDraw(Canvas canvas) {
// try to add a boder for this view.
canvas.getClipBounds(mRec);
// draw background
// canvas.drawColor(mbackgroundColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(DEFAULT_BACKGROUND_COLOR);
if (mBoderRadius > 0) {
mRectF.set(mRec);
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
} else {
canvas.drawRect(mRec, mPaint);
}
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mBoderWidth);
mPaint.setColor(DEFAULT_BORDER_COLOR);
mPaint.setAntiAlias(true);
if (mBoderRadius > 0) {
mRectF.set(mRec);
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
} else {
canvas.drawRect(mRec, mPaint);
}
super.onDraw(canvas);
}
The core of the problem is the padding, not AntiAliasing. The corner is not thicker, rather, it is the normal width. But, the straight line is clipped.
If you set the stroke width to 2, the really straight line width is 1 because the stroke is rectangular and the axis is the line x = 0. This means the rectangle is (left=0,up=-1,right=length,bottom=1), but the up -1 is outside of the canvas, so it will not be painted. And the corner is full width, because it is in the canvas.
So, you just to need set the padding.
Here is the code to make the rounded rect draw completely inside the canvas:
float pad = 1f;
mRectF.set(new RectF(mRec.left + pad, mRec.top + pad, mRec.right - pad, mRec.bottom - pad));
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
Set the antialias to the paint you are using to draw the red rectangle . For instance
mPaint.setAntiAlias(true);
I want this code to be help you.
public int mBoderWidth = 2;
public int mBoderColor;
public int mBoderRadius = 20;
public int mbackgroundColor;
public boolean isHaveBorder = true;
public boolean isHaveBackground = true;
RectF mRectF = new RectF();
Rect mRec = new Rect();
Paint mPaint = new Paint();
public MPCTextView(Context context) {
super(context);
// this.context = context;
}
#Override
protected void onDraw(Canvas canvas) {
// try to add a boder for this view.
canvas.getClipBounds(mRec);
// draw background
// canvas.drawColor(mbackgroundColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(DEFAULT_BACKGROUND_COLOR);
if (mBoderRadius > 0) {
mRectF.set(mRec);
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
} else {
canvas.drawRect(mRec, mPaint);
}
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mBoderWidth);
mPaint.setColor(DEFAULT_BORDER_COLOR);
mPaint.setAntiAlias(true);
if (mBoderRadius > 0) {
mRectF.set(mRec);
///////////// look at this code
mRectF.left += mBorderWidth/2;
mRectF.right -= mBorderWidth/2;
mRectF.top += mBorderWidth/2;
mRectF.bottom -= mBorderWidth/2;
canvas.drawRoundRect(mRectF, mBoderRadius, mBoderRadius, mPaint);
mRectF.left -= mBorderWidth/2;
mRectF.right += mBorderWidth/2;
mRectF.top -= mBorderWidth/2;
mRectF.bottom += mBorderWidth/2;
} else {
canvas.drawRect(mRec, mPaint);
}
super.onDraw(canvas);
}
I know I am answering this question very late but it may help others modify your code like below will work
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);