Follows is an SSCCE to understand animation timing, extracted from a much more complicated example. What this example when completed should do is create a circle and change its fill color between red and green every second. Right now it just draws a red circle and then nothing else. I've tried placing Runnable, Timer, Thread, and Handler code in various locations but it never seems to do anything. Another problem I've encountered in run() methods is the need for references to Canvas and the current color and the only way I've obtained them is by creating member data for them which, especially in the case of Canvas, seems like a bad idea. For what I'm ultimately doing, rotation and translation of graphic objects, SampleView and the accompanying Canvas seems to be almost certainly necessary so I want to leave SampleView in place. I think that's part of the problem, most examples of animation I've encountered place the timing code in an Activity but that won't work cleanly since the inner View's canvas must be used to update the color (unless I'm missing something).
Inside run methods I used variations on code like this.
if (color == Color.RED)
color = Color.GREEN;
else color = Color.RED;
canvas.drawOval(rectF, p);
hand.postDelayed(run, GET_DATA_INTERVAL);
Those references to color and canvas have been a pain.
package com.example.circles;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
public SampleView(Context context) {
super(context);
setFocusable(true);
p = new Paint();
}
Paint p;
int color;
RectF rectF = new RectF(0, 0, 50, 50);
#Override
protected void onDraw(Canvas canvas) {
p.setStyle(Paint.Style.FILL);
color = Color.RED;
p.setColor(color);
canvas.drawOval(rectF, p);
}
}
}
Related
Does anyone knows h!ow can I set conical gradient in android?
Like in this picture:
http://www.astutegraphics.com/images/blog/tutorials/how_to_create_true_gears_18_oct_2011/29.png
Sure, use a SweepGradient, then draw a circle with on a canvas.
An example can be found here. Have fun!
If you don't need too many colors, you can also define it via xml:
/res/drawable/sweepgradient.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:a="http://schemas.android.com/apk/res/android"
a:shape="oval"
a:dither="true">
<gradient a:type="sweep"
a:startColor="#FFFF0000"
a:centerColor="#FF0000FF"
a:endColor="#FF00FF00" />
</shape>
A SweepGradient is a native component so you cannot rely on Javas comfortable stacktraces. If you get non-stacktrace errors first check all native components.
Here is a quick example:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.SweepGradient;
import android.view.View;
public class GradientView extends View {
// Edit these values as you want!
private static int[] mColors={Color.RED, Color.GREEN, Color.BLUE};
private Paint mPaint=new Paint();
private boolean mSetShader=false;
public GradientView(Context context) {
super(context);
mPaint.setAntiAlias(true);
}
#Override
protected void onDraw(Canvas canvas) {
float cX=getWidth()/2F, cY=getHeight()/2F;
if (!mSetShader) {
mPaint.setShader(new SweepGradient(cX, cY, mColors, null));
mSetShader=true;
}
canvas.drawCircle(cX, cY, Math.min(cX, cY), mPaint);
}
}
Note that you may wan't to recreate the SweepGradient if the center changes (if the view resizes). I left out additional constructors and onMeasure for simplicity...
I'm trying to draw different random values from an array, but linking them with lines, so it looks likes the values of a continue function. I have done it quite good with this app:
package android.nacho.Graphic2D;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import java.util.Random;//included random
public class Graphic2D extends Activity{
DrawView drawView;
//private Button btnAsyncTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int randomInt;
//note a single Random object is reused here
Random randomGenerator = new Random();
int Maxsize=800;
int[] randomNumbers= new int[Maxsize];
for (int idx = 1; idx < Maxsize-1; ++idx){
randomInt = randomGenerator.nextInt(100);
randomNumbers[idx]=randomInt;
System.out.println("Random number: "+randomInt);
}
drawView = new DrawView(Graphic2D.this, randomNumbers, Maxsize);
drawView.setBackgroundColor(Color.WHITE);
setContentView(drawView);
}
}
package android.nacho.Graphic2D;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class DrawView extends View {
Paint paint = new Paint();
int[] values;
int Size, Offset;
public DrawView(Context context, int[] datainBytes, int size) {
super(context);
values=datainBytes;
Size=size;
paint.setColor(Color.BLACK);
}
#Override
public void onDraw(Canvas canvas) {
int cont2;
for(int cont=0; cont<Size-(1); cont++)
{
cont2=cont+1;
canvas.drawLine(cont, 500-(values[cont]) , cont+1, 500-(values[cont2]), paint);
}
}
}
The thing is, now I want to dram much more points, but in a dinamicall way so the new value is the one most at the right, the rest of the values move one pixel to the left and the one most of the left just don't appear. I was planning to this with a loop in the main Activity, so in each iteration the random values are all the same but the last one, and the others have move one position to the left in the array. The final effect should be something like a video.
But there is a problem, do App don't draw this dinamically, it just draw the last iteration of the loop. ¿Could anyone help me to solve this?
I was thinking in using AsyncTask for that, doing the points generation in the backgroun and sending the result to the update so draw in, but the script was a mess that didn't work, so I prefer to don't upload it.
Thank you very much for any suggestion.
I am developing a Car Race Game. I am able to move, stop, accelerate. But i want that when i press screen then car(bitmap of car image) should look like, it had jumped on its place.I am using surfaceviewto draw view
I do not want to use 3D openGL. Any help is much appreciated
finally i used.On touch event, i create a bigger bitmap and draw it on same place. So it will give zoom effect
Bitmap bitmapToZoom; // Create a Bitmap
// Now zoom it
bitmapToZoom=Bitmap.createScaledBitmap(bitmapToZoom, bitmapToZoom.getWidth()+30,bitmapToZoom.getHeight()+30, null);
//now draw it again
canvas.drawBitmap(bitmapToZoom, 0,0,null);
So now finally, Zooming actor on touch code will be like this. Class Name ZoomonTouc.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.SurfaceView;
public class ZoomonTouc extends SurfaceView {
public Bitmap mMyChracter;
public ZoomonTouc(Context context) {
super(context);
mMyChracter = BitmapFactory.decodeResource(context.getResources(),
R.drawable.ic_launcher);
setWillNotDraw(false);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mMyChracter, mMyChracter.getWidth()/2, mMyChracter.getHeight()/2, null);
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
RectF rectF = new RectF(mMyChracter.getWidth()/2, mMyChracter.getHeight()/2, mMyChracter.getWidth() + 100,
mMyChracter.getHeight() + 100);
if (rectF.contains(event.getX(), event.getY())) {
mMyChracter = Bitmap.createScaledBitmap(mMyChracter,
mMyChracter.getWidth() + 10, mMyChracter.getHeight() + 10,
false);
}
return true;
}
}
To test it properly create one activity and set above surface to activity background
setContentView(new ZoomonTouc(this));
I am trying to get a panel which has a canvas containing an image which i will place over another image and when i touch the screen the top(overlaying) image will be erased by means of a PoerterDuffXfermode(PorterDuff.Mode) etc ,, anyway I have the functionality done and dusted thanks to the help of a guy on this forum who provided some code which basically carried out exactly what I needed, but I'm having one slight problem,, the guys implementation of the code, will not allow me to reference the Panel class properly in XML to place the Panel on a pre defined XML (main.xml) file. its giving me an error stating
Custom view Panel is not using the 2- or 3-argument View constructors; XML attributes will not work
This is what my xml looks like on a basic scale (just the view in place within the outer linearlayout).
<com.easyscratch.full.Panel
xmlns:android="http://schemas.android.com/apk/res/android"
android:id ="#+id/easyCustView"
android:layout_width="300dp"
android:layout_height="300dp"
android:visibility="visible"
android:focusableInTouchMode="true"/>
The java is as followed .( PANEL CLASS)
package com.easyscratch.full;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
class Panel extends View
{
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mPaint;
Bitmap bitmap;
Canvas pcanvas ;
int x = 0;
int y =0;
int r =0;
public Panel(Context context) {
super(context);
Log.v("Panel", ">>>>>>");
setFocusable(true);
setBackgroundColor(Color.GREEN);
// setting paint
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
// getting image from resources
Resources r = this.getContext().getResources();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.foreground_image);
// converting image bitmap into mutable bitmap
bitmap = Bitmap.createBitmap(295, 260, Config.ARGB_8888);
pcanvas = new Canvas();
pcanvas.setBitmap(bitmap); // drawXY will result on that Bitmap
pcanvas.drawBitmap(bm, 0, 0, null);
}
#Override
protected void onDraw(Canvas canvas) {
// draw a circle that is erasing bitmap
pcanvas.drawCircle(x, y, r, mPaint);
canvas.drawBitmap(bitmap, 0, 0,null);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// set paramete to draw circle on touch event
x = (int) event.getX();
y = (int) event.getY();
r =20;
// Atlast invalidate canvas
invalidate();
return true;
}
}
BASIC MAIN CLASS CALLING MAIN.XML
package com.easyscratch.full;
import android.app.Activity;
import android.os.Bundle;
public class easyscratch extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
,, If only Someone cud tell me what im doing wrong , or maybe an alternative implementation of the
public Panel(Context context) {
super(context);
anyway thanks alot in advanced really would appriciate some help as soon as possible :)
CHEERS GUYS!
Your constructor for Panel must also, at least, have an AttributeSet field.
public Panel(Context context, AttributeSet attr){
super.(context, attr);
I am using RelativeLayout to position views at precise locations on the screen. This works as expected when using a view that say, draws a rectangle. But when using Android views like EditText, they are drawn shorter than specified by about 8 units. Clicking outside of the drawn EditText (but within the parameters specified by RelativeLayout) will, in fact, hit the EditText.
Here is some code to illustrate what I mean:
package com.DrawDemo;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
public class DrawDemo extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
RelativeLayout l = new RelativeLayout(this);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(100,100);
lp.leftMargin = 50;
lp.topMargin = 50;
DemoView demoview = new DemoView(this);
l.addView(demoview, lp);
EditText editText = new EditText(this);
l.addView(editText, lp);
setContentView(l);
}
private class DemoView extends View
{
public DemoView(Context context)
{
super(context);
}
#Override protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
canvas.drawPaint(paint);
}
}
}
If you execute this, you will notice that the EditText is noticeably shorter than the rectangle. I've tried mucking with onMeasure, setMinimumXXX, and just about everything else I can think of. So far, the only thing that works with some level of success is to just add 8 or so pixels to the height (8 seems to work better than trying a percentage of the height).
Next task will be to step into the source but was wondering if somebody has already solved this.
Thanks.
It's just because of the actual EditText background image that's used. Buttons are the same way, for some reason Google decided to draw the 9-patch background images with some extra transparent padding pixels. Really, the only solution, if it's a problem, would be to draw your own 9-patch, or modify the existing Android 9-patch to remove the extra pixels.