Android - Canvas draw glitch when overscroll effect in Android S+ - android

I'm using custom Drawable with animation to draw function diagram...
and I use PorterDuff.Mode.SRC_IN PorterDuffXfermode to draw its brightness bar (to clear the overlaped track)
with no overscroll effect, the brightness bar thumb is well drawn.
but if overscroll when animating, the thumb turn white.
pseudocode....
public class NotificationTileDrawable extends Drawable {
PorterDuffXfermode xfer = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
//...
#Override
public void draw(Canvas canvas) {
//draw other...
//draw track
canvas.drawRoundRect(...);
paint.setXfermode(xfer);
//draw thumb
canvas.drawRoundRect(...);
paint.setXfermode(null);
//draw other...
}
//other abstract methods...
}
how should i do to fix this? (without disable overscroll effect)
Thx

Related

Xamarin Android: How to draw on top of Canvas

I am writing a custom renderer for Xamarin.Forms. I am overriding the class ImageRenderer to do some tweaks to the image.
However, I want to overlay some parts of the image with circles, so I override the method void OnDraw(Canvas canvas).
Then I modify the Canvas a bit by drawing some circles:
protected override void OnDraw(Canvas canvas)
{
var paint = new Paint
{
Color = Color.Red
};
paint.SetStyle(Paint.Style.Fill);
foreach (var mapObject in _control.PointSource)
{
canvas.DrawCircle(mapObject.Location.X, mapObject.Location.Y, 100 / _scaleFactor, paint);
}
base.OnDraw(canvas);
}
However, everything is drawn on the background. The actual image is always on top. How can one draw circles on top of the image?
https://developer.xamarin.com/api/member/Android.Views.View.OnDraw/
In the docs they say the following:
the canvas on which the background will be drawn
So the current behaviour was expected.
I managed to fix it by moving the circle logic to the function: void Draw(Canvas canvas).

How to add Buttons and a background on GamePanel

My game's MainActivty set content view to a GamePanel that extends SurfaceView and Implements SurfaceHolder.Callback. How do i add buttons and set the background for the game? I tried adding buttons through xml but it only shows blackscreen.
When you use a surface view you are basically taking over responsibility for rendering the entire view.
So you implement a bunch of rendering routines and override onDraw( Canvas canvas )
Too render a background you would do something like this and call it from onDraw
private void drawBackground(Canvas canvas) {
Paint paint= getPaintForBackground();
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
}
private Paint getPaintForBackground() {
String key = "BACKGROUND";
Paint paint = mapPaints.get(key);
if (paint == null) {
paint = new Paint();
paint.setColor(symbolColor);
paint.setAlpha(50);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(1);
mapPaints.put(key, paint);
}
return paint;
}
You also render buttons and state changes in a similar fashion.
You can use an OnTouchListener to detect press state and color the
approriate button state changes.

Drawing a circle and high definition

In most of the android applications, the border of the circles are beautiful and the pixels in part of border of the circles are monotonic and beautiful. But when I draw a circle using the following code and when I see the result in my device, the pixels in part of border of the circle is like bitten apple.Such as when an ant has eaten around an apple.
My Code:
class Circle extends View {
Paint paint;
Circle(Context context) {
super(context);
paint = new Paint();
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.RED);
canvas.drawCircle(50,50,30,paint);
}
}
Turn on antialiasing to achieve it:
paint.setAntiAlias(true);
Please check this demo How to draw a circle in Android
set ANTI_ALIAS_FLAG flag true
For more info you may visit:
https://developer.android.com/reference/android/graphics/Canvas.html

Animating ActionBar's icon

I have an ActionBar icon (the main one on the left, not an action item) that I would like to animate.
I am setting my ActionBar's icon in my Activity like this:
getSupportActionBar().setIcon(icon)
where icon is a Drawable produced by a library that converts a custom XML view into a bitmap. This XML view is a RelativeLayout with a background image and a TextView on top.
Today, when I have to update the TextView I simply re-generate the icon and call setIcon again. Instead, I would like to get a hold of my TextView and apply some animation effect on it, like fade-out and then fade-in after updating it (maybe never having to call setIcon, just re-use the same one).
Not sure how to go about this. Can someone recommend an approach?
EDIT: trying this approach:
In MyActivity:
Drawable myDrawable = new MyDrawable();
supportActionBar.setIcon(myDrawable);
and:
public class MyDrawable extends Drawable {
private Paint paint;
private RectF rect;
public MyDrawable() {
this.paint = new Paint();
this.rect = new RectF();
}
#Override
public void draw(Canvas canvas) {
paint.setARGB(255, 0, 255, 0);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.FILL);
rect.right = 20f;
rect.bottom = 20f;
canvas.drawRoundRect(rect, 0.5f, 0.5f, paint);
}
#Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
paint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
}
Nothing shows up. I verified that onDraw gets called. Something suspicious to me is that canvas has both height & width set to 1.
A proper approach for it would be to forget the XML layout and create a custom Drawable.
An instance of this custom drawable will be set to the icon on the ActionBar and call invalidateSelf() whenever necessary to redraw (due to animation, for example).
The drawable can hold reference to other drawables (e.g. BitmapDrawable to have something from the /res/ folder or a Color or Gradient drawable for a background shade) and call (for example) bgDraw.draw(canvas) during the onDraw callback.
It can also draw stuff directly on the canvas that is given to it during onDraw callback. With the canvas you can draw circle, lines, areas, path and text directly on it.
edit:
very simple animation example (didn't check the code, likely typos):
private long animationTime;
public void doAnimation(){
animationTime = System.currentTimeMilis() + 3000; // 3 seconds
invalidateSelf();
}
public void onDraw(Canvas canvas){
// do your drawing.
// You can use difference between
// currentTimeMilis and animationTime for status/position
...
// at the end
if(animationTime > System.currentTimeMilis())
invalidateSelf();
}

Android - redraw canvas

I have 3 ImageViews. 1st and 2nd connected with red line. Also I have simple button. Here is a picture:
I want to connect 2nd & 3rd ImageViews with new Path line and change the first line color (for example to Green) when i clicking my button. Here is parts of my code:
public class SkillPath extends View {
Paint paint;
Path path;
... constructors
#Override
protected void onDraw(Canvas canvas) {
addPath (canvas);
}
//Here is my RED line
void addPath (Canvas canvas){
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStrokeWidth(3);
path.moveTo(110, 110);
path.lineTo(210, 110);
canvas.drawPath(path, paint);
Log.d ("Page 2","onDraw");
}
I can get all coordinates of all Views, but how can I redraw existing canvas? I suspect, I need to use invalidate(), but I do not know enough to do this. Need help.
The invalidate() method forces the View to be re-drawn.
So just apply the modification you need on your canvas and call invalidate() on the related View after these modifications.

Categories

Resources