Drawing white on android canvas makes canvas darker - android

I'm working on an android app of mine, but there is a small problem I'm having that is limiting its functionality. I'm using the android canvas to draw an animation to the screen (for a live wallpaper), but whenever I try drawing using Canvas.drawColor() with a color like #01ffffff (the last two digits are the alpha level), the canvas gets darker! How can that be? I'm drawing white over the canvas, albeit a very transparent white, but still a white. How can it be getting darker?
The color is getting drawn every frame. It is used to provide a fade to white animation, but it doesn't fade to white.
My code:
public class MyWallpaperService extends WallpaperService {
...
private void draw() {
handler.removeCallbacks(drawRunner);
SurfaceHolder holder = getSurfaceHolder();
Canvas canvas = null;
if (holder.getSurface().isValid()) {
if (visible) {
handler.postDelayed(drawRunner, refreshRate);
}
try {
canvas = holder.lockCanvas();
if (canvas != null) {
canvas.drawColor(backgroundColor);
}
} finally {
if (canvas != null)
try{
holder.unlockCanvasAndPost(canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
}
...
}
The draw() method is used to draw my wallpaper to the screen and within it has a call to canvas.drawColor(). The variable named backgroundColor is initialized to the color #01ffffff. So does anyone know why this is happening and what I can do to fix this? Thanks! (And any syntax errors in the code, like missing brackets, are probably due to my poor copy and pasting skills.)

Android color resources are defined with the first two digits as the transparency values. That may be your problem (as retailcoder suspected).

Related

How to add animations?

I'm trying to add different animations using matrix.setRotate (45), etc. to the Live Wallpaper, but it didn't work. All it did was showing the pictures in 45 degrees. I thought it would be rotating to 45 degrees?
I would like to add different animations to the slideshow live wallpaper like rotation, fading, translation, transformation, scaling, etc.
I even tried
matrix.setRotate(90);
matrix.setTranslate(100, 100);
but the pictures showed up very weird. Perhaps, there was any animation....
I know how to apply the animations from res/anim/animation.xml to NONE live wallpaper, but I can't seem to find a way to apply this animation.xml to the Live Wallpaper.
Is possible and easy way to apply animations to Live Wallpaper?
Thank you very much for your help in advance.
Java Code:
......
.....
....
private void drawFrame() {
// TODO Auto-generated method stub
final SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
drawPirate(c);
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
mhandler.removeCallbacks(drawrunnable);
if (mVisible) {
mhandler.postDelayed(drawrunnable);
}
}
private void drawPirate(Canvas c) {
// TODO Auto-generated method stub
Bitmap icon;
Matrix matrix = new Matrix();
matrix.setRotate(45);
icon = BitmapFactory.decodeResource(getResources(),pirates[i]);
c.drawBitmap(icon, matrix, null);
icon.recycle();
}
}
I'm not familiar with live wallpapers, but hopefully I can answer some of your other questions.
setRotate is not an animator, it rotates to its setting all at once
Good way to do this would be to create a thread for your drawFrame() and have it loop calling drawPirate(c), while incrementing the rotation value each time, so that you draw your image at setRotate(1), setRotate(2), etc until 45. You might want to look at the JetBoy android sample code for this kind of an implementation.
It is not good practice to allocate new things and decodeResources in the draw method. When you make multiple calls to it, it will have to create the new things every time and will slow things down a lot.

Detecting touch inside a irregular shape in ImageView

I have an ImageView which has a transparent drawable with a circle at the center like (http://wallpaperswide.com/circle_outline-wallpapers.html). Just that the circle is red, and the surrounding are not coloured but are transparent, it is a .png image. So now I will implement Canvas.ondraw(), and when while tracing the user goes outside the circle, the drawing should restart.
The doubt is:
1. How do I detect the boundaries of this image without hardcoding.
2. How do I detect that the user has clicked outside this, as this is not a regular rectangle.
I am doing this to help students trace alphabets, so I want the answer to be generic on the basis of any image in the shape of a letter.
Can it be done this way? If not, what better way can you suggest?
i'd go the easy route: just draw the image and check the colour of the point the user touched. if the alpha channel transparent, the user moved out.
the following code is untested (and very rough). i have no idea if the getDrawingCache trick works.
public class FooBar extends ImageView {
Bitmap b = null;
public FooBar(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
b = getDrawingCache(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE)
check((int) event.getX(), (int) event.getY());
return super.onTouchEvent(event);
}
private void check(int x, int y) {
if (b != null && Color.alpha(b.getPixel(x, y)) >= 0)
onMovedOutOfShape();
}
private void onMovedOutOfShape() {
Toast.makeText(getContext(), "You're out", Toast.LENGTH_SHORT).show();
}
}
What you're after is almost the same thing as "collision detection for irregular shapes". Googling on that will result in a zillion hits.
But if I had the problem to do, I'd probably bring in one of the game engines/frameworks such as Box2D, AndEngine, libGDX, or BatteryTech. I'd combine a few simple rectangles and curves to build up reactive places over each of my letter images and then use of of the library's pre-optimized collision detection algorithms to do the heavy lifting. I'd also at least look through their open source code to learn how they do their detection.

Flickering of bitmap on canvas in android

How to avoid image flickering when drawing on canvas.
Below code keep on running for images.The next image comes sliding from top but the previous image keep on flickering at back.I just want the previous image to become static.
void drawscreen()
{
SurfaceHolder holder = getSurfaceHolder();
try
{
Backgroundcanvas = holder.lockCanvas();
if (Backgroundcanvas != null)
{
if (top == true)
{ slide_from_top(); }
}
}
finally
{
if (Backgroundcanvas != null)
holder.unlockCanvasAndPost(Backgroundcanvas);
}
mHandler.removeCallbacks(mUpdateDisplay);
if (mVisible && count)
{
mHandler.postDelayed(mUpdateDisplay, interval);
count = false;
}
else
{
mHandler.postDelayed(mUpdateDisplay, 100);
}
}
I was also getting same problem, image flickering when drawing on canvas .
What I have done is making my worker thread(Not UI Thread) sleep for 10mlsec every time after using canvas drawing, and this time flickering is gone,
You can try this trick...
Clear canvas after each thread ends.
Just call Canvas.drawColor(Color.BLACK), or whatever color you want to clear your Canvas with.

live wallpaper doesn't slide smoothly on homescreen change

my live wallpaper doesn't slide smoothly most of the time on home screen change.
there is not a complicate coding for the position of background. it just use the xpixles that located on the onoffsetschanged method to adjust the x position of the wallpaper.
sometime it slide well same as in the sun rise live wallpaper app. but most of the other time it slide.. dunno how to describe it but its like a static sharp move. is there any idea about that guys.
best regards.
private void drawS() {
final SurfaceHolder holder = getSurfaceHolder();
canvas = null;
try {
canvas = holder.lockCanvas();
if (canvas != null) {
background = BitmapFactory.decodeResource(getResources(),
R.drawable.background);
canvas.drawBitmap(background, mXPixels, mYPixels, null);
}
}
finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
handler.removeCallbacks(runnableS);
if (visible) {
handler.postDelayed(runnableS, 25);
}
}
try to avoid resource creation in draw routine; remove this from drawS() function:
background = BitmapFactory.decodeResource(getResources(),
R.drawable.background);
and put it wherever you initialize your stuff and just use reference to background Bitmap later on.
If you take a look at logcat you'll see that there's a lot or resource shuffling and memory management going on (allocating memory for your resource, decoding bitmap image in it etc) every time you call your drawS(); ie every time you draw your background...
Cheers,
Ivica
I encountered the same problem and solved by following Ivica suggestion.
I moved the bitmap creation line inside the surface creation sub:
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
mybackground = BitmapFactory.decodeResource(getResources(), R.drawable.mybg);
}
In this way the sliding is very fluent

How I can draw an existent Canvas on another Canvas?

Now I need to draw a new Canvas in an existent Canvas (the parent Canvas), like Bitmap's works.
The logic is this:
Each Sprite can have others Sprite nodes (LinkedList<Sprite> nodes);
If don't have nodes (nodes = null) then, will draw the (Bitmap) Sprite.image directly to parent canvas, received on update method, like (currently working):
public void update(Canvas canvas){
if(this.nodes == null){
canvas.drawBitmap(this.image, ...);
}
...
}
If it have nodes, I need create a new Canvas, draw nodes bitmap on this, and draw the new Canvas on parent Canvas. This don't works, but the idea is like this:
public void update(Canvas canvas){
...
else { // this.nodes != null
Canvas newCanvas = new Canvas();
for(Sprite node: this.nodes){
node.update(newCanvas);
}
// Canvas working like Bitmap! (?)
canvas.drawCanvas(newCanvas, this.x, this.y, this.paint);
}
}
Real example usage: well, I have a Sprite called CarSprite. The CarSprite have a private class called WheelSprite extends Sprite. The CarSprite implements two nodes (two dimensional example) of WheelSprite, that will be positioned in the CarSprite to seems the whell of car. So far, no problem.
But if CarSprite is affected by a devil one object in the level, this will be turn transparent. I will do, for instance, objectOfCarSprite.paint.setAlpha(127);. The problem is, if I do it (currently working mode), only the car bitmap will turn transparent, but not the well, because it is drawed directly to global Canvas object.
This part does not influence much: currently, I'm getting the parent (of parentN...) Paint object alpha, and with some math, I get a transparent solution to wheel that works almost as well I need, but if, for instance, the WheelSprite object is over car bitmap, is possible to see the ground of car, like picture.
Exists a better way to do like I want, or only like work currently?
I do it. But is very slow, but works fine.
final Bitmap split = Bitmap.createBitmap(GameActivity.screenWidth,
GameActivity.screenHeight,
Bitmap.Config.ARGB_8888);
final Canvas subCanvas = new Canvas(split);
for(final Sprite sprite: this.nodes) {
sprite.update(subCanvas);
}
canvas.drawBitmap(split, this.x, this.y, this.paint);
First we need have a Canvas object (here just canvas);
After, we need make a Bitmap where we will draw. This need get a width and height from current canvas. I used a shortcut on this case;
Next, we need make a new Canvas, it will be passed to Sprite.nodes;
After all, we need draw the bitmap on global canvas;
Note: this works very well, but affect to much the speed.

Categories

Resources