I need to create a progressbar in arc shape. should I create a custom view for that? Or with the help of onDraw() method of ProgressBar class I can perform this thing? I also want to add marker on this progressBar like thermometer. Please suggest me any idea. Thanks.
Something like this:
protected synchronized void onDraw(Canvas canvas) {
int progress = this.getProgress();
int maxProgress = this.getMax();
//calc the progress to angles
float angleProgress = progress * 360 / maxProgress;
//create and set the arc paint
Paint arcPaint = new Paint();
arcPaint.setColor(0xff800000);
arcPaint.setAntiAlias(true);
arcPaint.setStyle(Style.FILL);
Rect arcRect = new Rect(); this.getDrawingRect(arcRect);
canvas.drawArc(new RectF(arcRect), -90, angleProgress,true, arcPaint);
}
For ref check this image arc shape progressbar
The default ProgressBar widget is not easily customisable, even for significantly less ambitious changes than this. In my opinion, it offers you no valuable behaviours in this context, other than acting as a carrier for minimum, maximum and current values. It also brings with it unwanted functionality such as the 'indeterminate' state.
Create a custom view by extending View and implementing onDraw() - as you have - and onMeasure().
Related
Well yes, I couldn't find anything that could help me for real so far... from StackOverflow to libraries and other things...
I need a custom shaped FrameLayout that is clipping his child inside of it. The problem is that I want this shape to be really custom, for example shirt / hat / etc..
So, somehow I want to clip child of FrameLayout inside the shirt let's say. I found something related to onDraw method, but I didn't find a way of getting pathData of a vector. . .
Any clear idea about how I could sort this up ( if possible ) is welcomed !
Thank you
You can use clip path. Your code can look something like:
private void updatePath() {
path = new Path();
// Draw your special shape...
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
canvas.clipPath(path);
return super.drawChild(canvas, child, drawingTime);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.clipPath(path);
super.onDraw(canvas);
}
I am working on slide menu view which extends SurfaceView but when I try to change size of the view a canvas does not change.
For debug purpose, I am changing size of the view calling method:
public void changeSize() {
width += 10;
getLayoutParams().width = width;
this.setLayoutParams(getLayoutParams());
}
Then in a draw function I paint the canvas white and draw red line diagonally across the view:
public void draw() throws Exception {
SurfaceHolder surfaceHolder = getHolder();
if (surfaceHolder.getSurface().isValid()) {
Canvas canvas = surfaceHolder.lockCanvas();
Log.i(TAG, "draw > canvas size: " + canvas.getWidth() + " " + canvas.getHeight() );
paint.setColor(Color.rgb(255,0,0));
paint.setStrokeWidth(5);
canvas.drawColor(Color.rgb(255, 255, 255));
canvas.drawLine(0, getLayoutParams().height, getLayoutParams().width, 0, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
What I see is a white rectangle with fixed size and part of red line:
demo.
Also, when I call this.getWidth() I get unchanged width.
Why view size is not changing? Is it the same reason that the canvas is not changing? What can I do to fix it?
I found reason for myself.
I did not mention about something - that I thought was not important - I called changeSize() via other thread than created the view and this is not allowed because: Only the original thread that created a view hierarchy can touch its views. And this problem was many time solved, e.g. here
I could use Activity.runOnUiThread() method but I did not want to pass the Activity to the view so I use View.post() method in the changeSize() like this:
Runnable changeParams = new Runnable() {
#Override
public void run() {
getLayoutParams().width = width;
setLayoutParams(getLayoutParams());
}
};
this.post(changeParams);
Update:
Maybe I do not know about proper way of using the UI Thread but whatever I tried I can not change view parameters smoothly.
Some workarounds to implement a slide menu:
Do [Android navigation Drawer][4] -- you can custiomize it with restictions e.g. you can not do the navigation drawer moving from top.
Use [Android animations][5] -- with it you can move or scale a view but can not resizing it.
I can not put more than 2 links with my reputation:
(4): developer.android.com/training/implementing-navigation/nav-drawer.html
(5): developer.android.com/training/animation/index.html
By doing getLayoutParams().width = width; you are changing layout params of the View. But you are performing drawing on a Canvas that owns SurfaceHolder, and not the one an ordinary View will provide you.
So, in order to change the size of the SurfaceView, you have to interact with SurfaceHolder:
surfaceView.getHolder().setFixedSize(width, height);
I want to show some static text over seek bar track.
It's different from what's normally required, i.e., showing current progress as tip or inside thumb.
I've tried both options of showing text; By adding a TextView over seekbar or by adding it dynamically in onDraw() method of my custom seekbar class.
NORMAL VIEW:
PROBLEM VIEW:
The issue is that the text is ABOVE both track and seekbar (as shown above). I somehow want to decrease the z-index of text so that it hides behind the thumb.
I'm overriding the onDraw method like:
#Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.getTextBounds(text, 0, text.length(), bounds);
paint.setTextSize(36);
int x = getWidth() / 2 - bounds.centerX();
int y = getHeight() / 2 - bounds.centerY();
canvas.drawText(text, x, y, paint);
}
Is there a way I can hide text behind thumbnail?
Any help is greatly appreciated.
I,m taking my first step into movement of bitmaps. From bits on the internet i,ve created this simple code. The bitmap moves across the screen from top left to top right it goes off the screen and back on at 0,0. What i want to do is add a button or method to manually move the image. I,m only using this single class and have noticed it does not use the main_activity xml Or does it?? If someone could show me on this 1 direction i can duplicate for the other directions. If youd like to add code so doesnt go off screen would be a bonus
public class MainActivity extends Activity {
int x=0;
int y=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new myView(this)); }
private class myView extends View{
public myView(Context context) {
super(context); }
#Override
protected void onDraw(Canvas canvas) {
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.richinch);
if (x < canvas.getWidth()){x +=10;}
else {x=0;}
canvas.drawBitmap(myBitmap, x, y, null);
invalidate();
}}}
Ive added this to the code and read a little on OnTouch listener. How would i add that to the region or Rectangle this would be very helpfull so effectively i,m using the Bitmap as a button if was button id know with onclick, Basicall im trying to make 2 Bitmap buttons to move the image Left Right for now.Eventually all directions. Please use names im using unless creating summit eg int etc
Paint green = new Paint();
green.setColor(Color.RED);
green.setStyle(Paint.Style.FILL);
////creating the shape////
Rect rect= new Rect();
rect.set(0, 0,x+50, x+50);
canvas.drawRect(rect,green);
Region region = new Region(0, 950, 100, 1030);
I am not exactly sure what you want to achieve, but if you would like to make an animation, avoid using onDraw() and just let ObjectAnimator do the "moving" for you. Here's a detailed tutorial on it.
The minimum code you need:
ObjectAnimator animation = ObjectAnimator.ofFloat(yourObject, "x", xDest);
animation.setDuration(500); // milliseconds
animation.start();
You are not using any xml
this part here:
setContentView(new myView(this)); is where you would add your xml file setContentView(R.layout.mainxml)
If you want to move around a bitmap with the touch of your finger check out these tutorials. They do exactly this and you will learn to use a SurfaceView
http://www.eis4u.com/2012/02/13/playing-with-graphics-in-android-part-i/
http://www.eis4u.com/2012/02/13/playing-with-graphics-in-android-part-ii/
http://www.eis4u.com/2012/02/13/playing-with-graphics-in-android-part-iii/
I'm writing a custom view that displays signals. In order to shorten my onDraw() time I cache everything I've drawn so far in a Bitmap and just append to that in every onDraw() call. By doing this I can save huge amounts of time since I only need to draw a few fixels at a time instead of redoing the whole thing.
There is on thing bothering me though - it appears as drawing directly to the provided canvas provides a more "accurate" drawing than drawing on the bitmap first and then drawing the bitmap on the canvas. By looking at the lower part of the following picture you can see the difference:
I uploaded a demo project displaying the discrepancy at https://github.com/gardarh/android-uglybitmapdrawing/ but the relevant code is as follows:
#Override
public void onDraw(Canvas canvas) {
if(cachedBitmap == null) {
cachedBitmap = Bitmap.createBitmap(getWidth(), 200, Config.ARGB_8888);
cachedCanvas = new Canvas(cachedBitmap);
}
for(int i = 0; i < COORDS.length; i++) {
float[] curCoords = COORDS[i];
canvas.drawLine(curCoords[0], curCoords[1], curCoords[2], curCoords[3], linePaint);
cachedCanvas.drawLine(curCoords[0], curCoords[1], curCoords[2], curCoords[3], linePaint);
}
canvas.drawBitmap(cachedBitmap, 0, 120, null);
}
Why are the two traces not the same and more importantly, how can I make the lower trace look like the upper one?
The reason for the differences is that the canvas drawing is done by hardware acceleration (GPU), and the bitmap drawing is done by software (CPU). If you disable hardware acceleration, they become the exact same.
If you multiply the X coordinates by 10, you will see that the difference is in the way lines are joined. These are minor one pixel difference and I wouldn't bother with them. I am not sure which one is the more accurate, they seem like just slightly different implementations.
Android framework API provides 2D drawing APIs for simple animation that does not require major dynamic changes.
There are two ways of implementation using these API.
1. Drawing to a View
2. Drawing on a Canvas
1.Drawing a circle to View
Drawing to view is a better option when your UI does not require dynamic changes in the application.
This can be achieved simply by extending the View class and define an onDraw() callback method.
Use the Canvas given to you for all your drawing,
using various Canvas.draw...() methods (Ex: canvas.drawCircle(x / 2, y / 2, radius, paint);). onDraw() is a callback method invoked when the view is initially drawn.
Below is a simple example code to draw a circle:-
MainActivity.java
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
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);
int x = getWidth();
int y = getHeight();
int radius;
radius = 100;
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
// Use Color.parseColor to define HTML colors
paint.setColor(Color.parseColor("#FB9J2F"));
canvas.drawCircle(x / 2, y / 2, radius, paint);
}
} }
2. Drawing rectangle on a canvas
To draw dynamic 2D graphics where in your application needs to regularly re draw itself, drawing on a canvas is a better option. A Canvas works for you as an interface, to the actual surface upon which your graphics will be drawn.
If you need to create a new Canvas, then you must define the bitmap upon which drawing will actually be performed. The Bitmap is always required for a Canvas.
The below example explains to draw a rectangle:-
activity_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="match_parent"
android:layout_height="match_parent"
android:id="#+id/mylayout"> </LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Paint paint = new Paint();
paint.setColor(Color.parseColor("#DD4N5C"));
Bitmap bitmap = Bitmap.createBitmap(512, 800, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawRect(150, 150, 250, 250, paint);
LinearLayout layout = (LinearLayout) findViewById(R.id.mylayout);
layout.setBackgroundDrawable(new BitmapDrawable(bitmap));
}
}
I disagree that you are saving much by going the bitmap route. You might consider a data structure that stores the drawn signal and converting this to a JSON object that can be serialized/deserialized.
As for your question, this is an educated guess but it has more to do with rescaling of the drawn signal, since you are not using getHeight() when you create the bitmap.