it seems I have a problem understanding classes. It would be great if someone could help.
I'm trying to populate my Smartphone screen (android) with 3 circles of different color.
My problem is that by using the code below I only get one (blue) circle.
I considered that the Problem is that the y-value isn't set correctly and the 3 circles are hiding each other (so that only the blue one is visible). But when I log the y-value of the 3 circle objects, the y-values seem to be correct (200,500,800)
Whats am I doing wrong?
Thanks for your help in advance.
public class MainActivity extends Activity {
public Circle circleR;
public Circle circleG;
public Circle circleB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
circleR = new Circle(this, 200, 255, 0, 0);
setContentView(circleR);
circleG = new Circle(this, 500, 0, 255, 0);
setContentView(circleG);
circleB = new Circle(this, 800, 0, 0, 255);
setContentView(circleB);
}
}
public class Circle extends View {
public Paint paint;
public int y;
public Circle(Context context,int y, int r, int g, int b){
super(context);
paint=new Paint();
paint.setColor(Color.rgb(r,g,b));
this.y=y;
}
#Override
protected void onDraw(Canvas canvas){
canvas.drawCircle(30, this.y,30, paint);
}
}
The problem lies in setting the content view multiple times. Only the view set as last (the one with a blue circle) will be visible. If you want multiple circles to be visible at the same time you should draw them on one canvas localized inside one view. I rearranged your code so that it does what you wanted:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CirclesView circlesView = new CirclesView(this);
setContentView(circlesView);
}
}
public class CirclesView extends View {
public Circle circleR;
public Circle circleG;
public Circle circleB;
public CirclesView(Context context) {
super(context);
circleR = new Circle(200, 255, 0, 0);
circleG = new Circle(500, 0, 255, 0);
circleB = new Circle(800, 0, 0, 255);
}
#Override
protected void onDraw(Canvas canvas){
circleR.draw(canvas);
circleG.draw(canvas);
circleB.draw(canvas);
}
}
public class Circle {
public Paint paint;
public int y;
public Circle(int y, int r, int g, int b) {
paint = new Paint();
paint.setColor(Color.rgb(r,g,b));
this.y=y;
}
public void draw(Canvas canvas) {
canvas.drawCircle(30, this.y,30, paint);
}
}
Circle knows how to draw itself on a canvas which will be provided to it by a view.
Related
I've setted up a simple application that once I have structured a Canvas puts an Rectangle inside it. I was asking myself if there's a method that allows me to fill that rettangle with an image.
This is my Canvas Class code:
public class MioCanvas extends View {
Paint paint;
Rect rect;
public MioCanvas(Context context) {
super(context);
paint = new Paint();
rect = new Rect();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.GRAY);
paint.setStrokeWidth(3);
canvas.drawRect(0, 1999999, canvas.getWidth() / 2, canvas.getHeight() / 2, paint);
}
}
This is my activity code:
public class MainActivity extends AppCompatActivity {
MioCanvas mioCanvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mioCanvas = new MioCanvas(this);
mioCanvas.setBackgroundColor(Color.GREEN);
setContentView(mioCanvas);
}
}
You can use a Bitmap with your custom rect as input.
Rect rectangle = new Rect(0,0,100,100);
canvas.drawBitmap(bitmap, null, rectangle, null);
I ran into this app concept by Oleg Frolov on Dribble.
The implementation seems pretty basic, with a horizontal ScrollView and a button which triggers the reveal animation.
I want to know :-
How to implement the vertical ProgressBar as the background of the
countdown activity
How to sync the progress of the ProgressBar, and the TextView's text change with the Chronometer/ System clock.
this project show you how to implement such a progress bar.
that is very simple to do with a custom drawable, there's no need to use libraries.
below is an UNTESTED example on how to do it.
public class CustomDrawable extends Drawable {
private final int color1;
private final Paint paint;
float level;
public CustomDrawable(int color1, int color2) {
this.color1 = color1;
paint = new Paint();
paint.setColor(color2);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
}
#Override protected boolean onLevelChange(int level) {
invalidateSelf();
return true;
}
#Override public void draw(Canvas canvas) {
canvas.drawColor(color1);
level = getLevel() / 100f;
canvas.drawRect(
0,
canvas.getHeight() * level, // tweak this line if not drawing properly
canvas.getWidth(),
canvas.getHeight(), paint);
}
#Override public void setAlpha(int alpha) {
}
#Override public void setColorFilter(ColorFilter colorFilter) {
}
#Override public int getOpacity() {
return 0;
}
}
on the background view just use this drawable like:
background.setBackground(new CustomDrawable(color1, color2));
then to update the value u call
background.getBackground().setLevel(... between 0-100...);
If I use an Android L device and resume my app, the SurfaceViews are cut.
The details of occurrence condition are as follows:
- Using Android L (It is originally L, not updated to L)
- The SurfaceView is larger than the display.
- The left-top of SurfaceView is more to the left or top of the display.
- Resuming the app from the background apps list, not the icon in the app list.
I tried to reset size, gravity, clip bounds, etc., however, none had effect.
I want to repair the SurfaceView cut, you do not have some idea?
The sample code is as follows:
[Activity]
public class ViewTestActivity extends Activity {
private DrawSurfaceView mDrawSurfaceView;
private int overDispW;
private int overDispH;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point dispP = new Point();
display.getSize(dispP);
overDispW = (int) (dispP.x * 1.5);
overDispH = (int) (dispP.y * 1.5);
FrameLayout.LayoutParams overSizeParams = new FrameLayout.LayoutParams(overDispW, overDispH);
//If gravity is Gravity.LEFT|Gravity.TOP, there is no cut.
overSizeParams.gravity = Gravity.CENTER;
mDrawSurfaceView = new DrawSurfaceView(this);
setContentView(mDrawSurfaceView, overSizeParams);
}
}
[SurfaceView]
public class DrawSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private Paint mPaintRed;
private Paint mPaintBlue;
private Paint mPaintGreen;
private Paint mPaintYellow;
private SurfaceHolder mHolder;
public DrawSurfaceView(Context context) {
super(context);
mPaintRed = new Paint();
mPaintRed.setColor(Color.argb(255, 255, 0, 0));
mPaintBlue = new Paint();
mPaintBlue.setColor(Color.argb(255, 0, 0, 255));
mPaintGreen = new Paint();
mPaintGreen.setColor(Color.argb(255, 0, 255, 0));
mPaintYellow = new Paint();
mPaintYellow.setColor(Color.argb(255, 255, 255, 0));
mHolder = getHolder();
mHolder.setFormat(PixelFormat.RGBA_8888);
mHolder.addCallback(this);
}
public void onDraw(Canvas canvas){
super.onDraw(canvas);
drawRect(canvas);
}
private void drawRect(Canvas canvas) {
int w = canvas.getWidth();
int h = canvas.getHeight();
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
canvas.drawRect(0, 0, w/2, h/2, mPaintRed);
canvas.drawRect(w/2, h/2, w, h, mPaintBlue);
canvas.drawRect(w/2, 0, w, h/2, mPaintGreen);
canvas.drawRect(0, h/2, w/2, h, mPaintYellow);
}
public void doDraw(){
Canvas canvas = mHolder.lockCanvas();
if(canvas != null){
drawRect(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
doDraw();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
doDraw();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
Right side of view has been cut.
I have a problem I was trying to solve for almost 2 days. (It ended up by switching to OpenGL :D)
Anyway... I have Canvas and I am trying to do a simple snake game. Just for this problem imagine our snake is made up from 5x5 pixels rectangles, he is leaving the trail (no clearing) and moving to the right from 0, 50 position... here is the code:
public class Snake extends AnimationWallpaper {
#Override
public Engine onCreateEngine() {
return new SnakeEngine();
}
class SnakeEngine extends AnimationEngine {
int i = 0;
Paint paint = new Paint();
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
// By default we don't get touch events, so enable them.
setTouchEventsEnabled(true);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xOffsetStep, float yOffsetStep, int xPixelOffset,
int yPixelOffset) {
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
xPixelOffset, yPixelOffset);
}
#Override
public Bundle onCommand(String action, int x, int y, int z,
Bundle extras, boolean resultRequested) {
if ("android.wallpaper.tap".equals(action)) {
}
return super.onCommand(action, x, y, z, extras, resultRequested);
}
#Override
protected void drawFrame() {
SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
draw(c);
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
}
void draw(Canvas c) {
//c.save();
//c.drawColor(0xff000000);
paint.setAntiAlias(true);
// paint the fill
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
c.drawRect(i*5, 50, (i+1)*5, 55, paint);
//c.restore();
}
#Override
protected void iteration() {
i++;
super.iteration();
}
}
}
And here is output:
And that is not all, when it draws its kinda shifting... meaning what you see is shifted to the right side so it doesnt actualy stand in the same place...
If you have any idea why is it behave like that, please tell me!
In canvas, there's a reusability functionality which practically just add new drawings to whatever is in the canvas, hence if you are drawing 1 square at the time, the next time you will have whatever u had before +1, if you don't want that, and you want to fully manipulate every single draw from scratch, just add this line of code before to start drawing
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
It will clear anything you had in the previous state of the canvas, and you can start again drawing whatever you want...
Hope It Helps!
Regards!
I've the following code below.
public class CompassActivity extends Activity {
public class OuterCircle extends View {
Paint paint = new Paint();
Path path = new Path();
private static final String s = "Hello world example";
public OuterCircle(Context context) {
super(context);
init();
}
private void init() {
paint.setColor(Color.WHITE);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2);
paint.setAntiAlias(true);
}
private void drawDegreesOnCircle(Canvas c) {
path.addCircle(getWidth()/2, getHeight()/2, 180, Direction.CW);
c.drawTextOnPath(s, path, 0, 10, paint);
}
public void onDraw(Canvas c) {
int cx = getWidth()/2;
int cy = getHeight()/2;
c.drawCircle(cx, cy, 170, paint);
drawDegreesOnCircle(c);
}
}
}
The circle is drawn successfully. However, the string I've specified is not displayed. There is no error or warning in the code. Am I missing anything in my code? I'm trying to display the string around the circle. I got stuck here. :D
I've fixed the above issue by adding
setLayerType(View.LAYER_TYPE_SOFTWARE, null)
It is required to use the above method along with the
Canvas.drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)
for Android API level 11 or higher. The string is now displayed successfully around the circle. Here is the correct code.
public class CompassActivity extends Activity {
public class OuterCircle extends View {
Paint paint = new Paint();
Path path = new Path();
private static final String s = "Hello world example";
public OuterCircle(Context context) {
super(context);
init();
}
private void init() {
paint.setColor(Color.WHITE);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2);
paint.setAntiAlias(true);
}
private void drawDegreesOnCircle(Canvas c) {
path.addCircle(getWidth()/2, getHeight()/2, 180, Direction.CW);
c.drawTextOnPath(s, path, 0, 10, paint);
setLayerType(View.LAYER_TYPE_SOFTWARE, null); // Required for API level 11 or higher.
}
public void onDraw(Canvas c) {
int cx = getWidth()/2;
int cy = getHeight()/2;
c.drawCircle(cx, cy, 170, paint);
drawDegreesOnCircle(c);
}
}
}
You're missing a call to drawPath()
private void drawDegreesOnCircle(Canvas c) {
path.addCircle(getWidth()/2, getHeight()/2, 180, Direction.CW);
c.drawPath(path, paint);
c.drawTextOnPath(s, path, 0, 10, paint);
}
A very simple example just to get text in an angle on the center of the display.
public class DrawSomeText extends View {
Paint mPaint;
public DrawSomeText(Context context) {
super(context);
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
}
#Override
public void onDraw(Canvas canvas) {
Path path = new Path();
path.moveTo(getWidth()/2, getHeight()/2);
path.lineTo(getWidth(), getHeight());
path.close();
canvas.drawPath(path, mPaint);
canvas.drawTextOnPath("Hello World", path, 0, 0, mPaint);
}
}