I have a custom android View that draws a waveform on the screen.
A variable, cursorTask is a TimerTask that somehow becomes null in between startCursor finishing execution and stopCursor being called. I don't see how this can be happening as it is private and all of the WaveView's startCursor functions are called.
public class WaveView extends View {
private Audio audio;
Paint wavePaint;
Paint progressPaint;
Paint barPaint;
private int progress;
private int maxProgress = 100;
private Timer timer;
private TimerTask cursorTask;
public WaveView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
timer = new Timer();
wavePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
wavePaint.setColor(Color.BLUE);
wavePaint.setStyle(Paint.Style.FILL);
progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
progressPaint.setColor(Color.RED);
progressPaint.setStrokeWidth(2.0f);
barPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
barPaint.setColor(Color.CYAN);
barPaint.setAlpha(100);
}
public void setAudio(Audio audio){
this.audio = audio;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(audio != null && audio.waveValues != null && !audio.waveValues.isEmpty()){
int w = canvas.getWidth();
int h = canvas.getHeight();
canvas.drawRect(new Rect(0, 0, w*audio.bars/Rhythm.maxBars, h), barPaint);
Path path = new Path();
path.moveTo(0,h);
for(int i = 0; i < 100; i++){
int x = i * w/100;
if(audio.waveValues.size() <= i){
path.lineTo(x, h);
break;
}
int y = Math.round(h-audio.waveValues.get(i)*h);
path.lineTo(x, y);
}
path.lineTo(w,h);
canvas.drawPath(path, wavePaint);
if(0 < progress){
float x = progress*w*audio.bars/maxProgress/Rhythm.maxBars;
canvas.drawLine(x, h, x, 0, progressPaint);
}
}
}
public void startCursor(int msLoopDuration){
progress = 0;
cursorTask = new TimerTask() {
#Override
public void run() {
progress = (progress+1) % maxProgress;
postInvalidate();
}
};
timer.scheduleAtFixedRate(cursorTask, 0, msLoopDuration/maxProgress);
}
public void stopCursor(){
cursorTask.cancel();
}
}
I call it by finding the WaveView in the convertView in getView() in the adapter where the WaveView is.
WaveView wave = (WaveView)convertView.findViewById(R.id.waveform);
wave.startCursor(Rhythm.msBarPeriod()*audio.bars);
Any help would be greatly appreciated.
Related
I'm trying to create a "clear all" button in my app, but it doesn't work. This is the code I use to create and use the canvas:
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(LAYER_TYPE_HARDWARE, null);
startActivity = System.currentTimeMillis();
setupDrawing();
}
public void setDimension (DisplayMetrics displaymetrics) {
height = displaymetrics.heightPixels;
width = displaymetrics.widthPixels;
diameter = width;
if (height < width){
diameter = height;
}
offset = (int) (0.32*diameter);
diameter -= offset;
String imageName = protocol+draw;
}
//setup drawing
private void setupDrawing(){
//prepare for drawing and setup paint stroke properties
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(5);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
//size assigned to view
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
//draw the view - will be called after touch event
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
canvas.drawRect(width/2 - diameter/2 ,
(70),
width/2 + diameter/2,
1100, drawPaint);
}
And this is the code I used to clear the screen, but pressing the button nothing showed up:
public void restoreDraw () {
drawPath = null;
canvasBitmap = Bitmap.createBitmap(width, 350, Bitmap.Config.ARGB_8888);
drawPath = new Path();
}
Should I clear the bitmap canvas, right?
You have to add requestLayout() inside restoreDraw() method.
public void restoreDraw () {
drawPath = null;
canvasBitmap = Bitmap.createBitmap(width, 350, Bitmap.Config.ARGB_8888);
drawPath = new Path();
requestLayout();
}
Hi I currently have a SurfaceView Runnable public class mapsLayout extends SurfaceView implements Runnable { which draws lines based on current geolocation. My previous solution involved having a main activity which contains the Android location manager - using a FusedLocationProviderClient as recommended by the tutorials provided by Google - and then calling the SurfaceView.
mainActivity with Android location manager -> 'SurfaceView'
However this means that the SurfaceView resets every time the location changes which happens every 10000 ticks.
Is there a way for the SurfaceView to contain the Android location manager.
If it helps I have my SurfaceView Runnable code below
public class mapsActivityLayout extends SurfaceView implements Runnable {
MyThread draw = null;
boolean canDraw = false;
Bitmap map;
SurfaceHolder surfaceHolder;
Context mContext;
Paint paint;
ArrayList<String> endNodes = new ArrayList<String>();
int bitmapX;
int bitmapY;
int viewWidth;
int viewHeight;
Paint red_paintbrush_fill, blue_paintbrush_fill, green_paintbrush_fill;
Paint red_paintbrush_stroke, blue_paintbrush_stroke, green_paintbrush_stroke;
Path line;
Path circle;
public mapsActivityLayout(Context context, ArrayList<String> endNodes) {
super(context);
this.endNodes = endNodes
mContext = context;
surfaceHolder = getHolder();
paint = new Paint();
paint.setColor(Color.DKGRAY);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
draw = new MyThread(viewWidth, viewHeight);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = true;
options.inMutable = true;
map = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.mapimage, options);
setUpBitmap();
}
#Override
public void run() {
Canvas canvas;
prepPaintBrushes();
while (canDraw) {
//draw stuff
if (surfaceHolder.getSurface().isValid()) {
int x = draw.getX();
int y = draw.getY();
//int radius = draw.getRadius();
canvas = surfaceHolder.lockCanvas();
canvas.save();
canvas.drawBitmap(map, bitmapX, bitmapY, paint);
ArrayList<Double> currentLocation = convertGeoToPixel(currentLat, currentLon);
ArrayList<Double> destination = convertGeoToPixel(destinationLat, destinationLat);
int width = 2699;
int height = 2699;
canvas.drawCircle(currentX, currentY, 20, red_paintbrush_fill);
canvas.drawCircle(destX, destY, 20, green_paintbrush_fill);
path.rewind();
canvas.restore();
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
private void updateFrame(int newX, int newY) {
draw.update(newX, newY);
}
/**
* Calculates a randomized location for the bitmap
* and the winning bounding rectangle.
*/
private void setUpBitmap() {
bitmapX = (int) Math.floor(
Math.random() * (viewWidth - backGround.getWidth()));
bitmapY = (int) Math.floor(
Math.random() * (viewHeight - backGround.getHeight()));
}
public void pause() {
canDraw = false;
while (true) {
try {
thread.join();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void resume() {
canDraw = true;
thread = new Thread(this);
thread.start();
}
private void prepPaintBrushes() {
red_paintbrush_fill = new Paint();
red_paintbrush_fill.setColor(Color.RED);
red_paintbrush_fill.setStyle(Paint.Style.FILL);
green_paintbrush_stroke = new Paint();
green_paintbrush_stroke.setColor(Color.GREEN);
green_paintbrush_stroke.setStyle(Paint.Style.STROKE);
green_paintbrush_stroke.setStrokeWidth(10);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setUpBitmap();
updateFrame((int) x, (int) y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
updateFrame((int) x, (int) y);
invalidate();
break;
default:
}
return true;
}
}
thread code
public class MyThread extends Thread {
private int mX;
private int mY;
public MyThread(int viewWidth, int viewHeight) {
//super()
mX = viewWidth / 2;
mY = viewHeight / 2;
}
/**
* Update the coordinates of the map.
*
* #param newX Changed value for x coordinate.
* #param newY Changed value for y coordinate.
*/
public void update(int newX, int newY) {
mX = newX;
mY = newY;
}
public int getX() {
return mX;
}
public int getY() {
return mY;
}
}
I have implemented zoom on my custom made view which draws a grid onto a canvas, but the zooming won't work if I put both fingers on the screen simultaneously. I have to first put one, then the other.
I followed this blog post by Adam Powell to implement zoom, and made this custom view:
public class ZoomView extends View{
private float width;
private float height;
Paint lineColor;
Paint bgColor;
private float mScaleFactor;
private ScaleGestureDetector scaleDetector;
public CanvasView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
lineColor = new Paint();
lineColor.setColor(getResources().getColor(R.color.white));
bgColor = new Paint();
bgColor.setColor(getResources().getColor(R.color.black));
mScaleFactor = 1;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh){
width = w/9;
height = h/9;
super.onSizeChanged(w,h,oldw,oldh);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor); //for zooming
for(int i=0; i <= 9; i++){
canvas.drawLine(0,i*height, 9*width,i*height,lineColor);
canvas.drawLine(i*width, 0, i*width, 9*height, lineColor);
}
canvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent ev){
mScaleDetector.onTouchEvent(ev);
return true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
setMeasuredDimension(800, 1000);
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
}
So why is the zooming behaving this way?
Any help would be greatly appreciated. Thanks!
This may look like a silly question, but does the multi touch behavior work on other apps (Maps for example) at this device?
I've tested your code (with minor changes, see below) on an LG Optimus Black, Android 4.0.3, and it worked, both fingers simultaneously.
package com.example.teste;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
public class ZoomView extends View {
private float width;
private float height;
Paint lineColor;
Paint bgColor;
private float mScaleFactor;
private ScaleGestureDetector mScaleDetector;
public ZoomView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
lineColor = new Paint();
lineColor.setColor(getResources().getColor(R.color.ics_blue_bright));
bgColor = new Paint();
bgColor.setColor(getResources().getColor(R.color.black));
mScaleFactor = 1;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w / 9;
height = h / 9;
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor); // for zooming
for (int i = 0; i <= 9; i++) {
canvas.drawLine(0, i * height, 9 * width, i * height, lineColor);
canvas.drawLine(i * width, 0, i * width, 9 * height, lineColor);
}
canvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
mScaleDetector.onTouchEvent(ev);
return true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(800, 1000);
}
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
}
Here is the code for Drawing and Undoing but unable to join with Erasing.
It is either Drawing + Erasing or Drawing + Undoing but cannot three of these.
public class Drawing extends View {
private Paint mPaint, mBitmapPaint;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private int color, size, state;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
private ArrayList<Integer> colors = new ArrayList<Integer>();
private ArrayList<Integer> sizes = new ArrayList<Integer>();
public Drawing(Context c) {
super(c);
}
public Drawing(Context c,int width, int height, int size, int color, int state) {
super(c);
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
// mBitmapPaint = new Paint(Paint.DITHER_FLAG);
// mBitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
setColor(color);
setSize(size);
setState(state);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
// canvas.drawColor(Color.TRANSPARENT);
// canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
//
// if (state == 0)
// mBitmap.eraseColor(Color.TRANSPARENT);
for (int i = 0; i < paths.size(); i++) {
mPaint.setColor(colors.get(i));
mPaint.setStrokeWidth(sizes.get(i));
canvas.drawPath(paths.get(i), mPaint);
}
mPaint.setColor(color);
mPaint.setStrokeWidth(size);
canvas.drawPath(mPath, mPaint);
}
public void setColor(int color) {
this.color = color;
}
public void setSize(int size) {
this.size = size;
}
public void setState(int state) {
this.state = state;
// if (state == 0)
// mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
// else
// mPaint.setXfermode(null);
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
sizes.remove(sizes.size() - 1);
colors.remove(colors.size() - 1);
invalidate();
}
}
private void touch_start(float x, float y) {
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
colors.add(color);
sizes.add(size);
paths.add(mPath);
mPath = new Path();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
I tried to made color to transparent but it does not make sense because not changing the pixel but is create new path.
The below can be used to draw erase, emboss, save to gallery, blur. You can use the code to add undo and redo functionality. The below code works fine. You can slo check FingerPaint.java from the samples folder of your adk under api demos in the grapics folder.
Creating a spray effect on touch draw in android. This link will help you create spray effect by spraying dots.
public class FingerPaintActivity extends GraphicsActivity
implements ColorPickerDialog.OnColorChangedListener {
private Paint mPaint;
private MaskFilter mEmboss;
private MaskFilter mBlur;
Button b;
Dialog dialog;
static MyView mv;
File f;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
mv= new MyView(this);
mv.setDrawingCacheEnabled(true);
ll.addView(mv);
b= (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
final CharSequence[] items = {"Pick Color", "Emboss", "Blur","Erase","SaveToGallery"};
AlertDialog.Builder builder = new AlertDialog.Builder(FingerPaintActivity.this);
builder.setTitle("Options");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if(item==0)
{
new ColorPickerDialog(FingerPaintActivity.this, FingerPaintActivity.this, mPaint.getColor()).show();
}
if(item==1)
{
if (mPaint.getMaskFilter() != mEmboss) {
mPaint.setMaskFilter(mEmboss);
} else {
mPaint.setMaskFilter(null);
}
}
if(item==2)
{
if (mPaint.getMaskFilter() != mBlur) {
mPaint.setMaskFilter(mBlur);
} else {
mPaint.setMaskFilter(null);
}
}
if(item==3)
{
mPaint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.CLEAR));
}
if(item==4)
{
saveImage();
}
}
});
builder.show();
}
});
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(20);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
public void colorChanged(int color) {
mPaint.setColor(color);
}
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context mcontext;
public MyView(Context c) {
super(c);
mcontext=c;
mPath = new Path();
mBitmapPaint = new Paint();
mBitmapPaint.setColor(Color.RED);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
Display display = ( (Activity) mcontext).getWindowManager().getDefaultDisplay();
float w = display.getWidth();
float h = display.getHeight();
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawLine(0, 0, w, 0,mBitmapPaint);
canvas.drawLine(0, 0, 0, h,mBitmapPaint);
canvas.drawLine(w,h,w,0,mBitmapPaint);
canvas.drawLine(w, h, 0,h , mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
// kill this so we don't double draw
mPath.reset();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
public void saveImage()
{
AlertDialog.Builder editalert = new AlertDialog.Builder(FingerPaintActivity.this);
editalert.setTitle("Please Enter the name with which you want to Save");
final EditText input = new EditText(FingerPaintActivity.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
input.setLayoutParams(lp);
editalert.setView(input);
editalert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mv.setDrawingCacheEnabled(true);
String name= input.getText().toString();
Bitmap bitmap = mv.getDrawingCache();
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/MapleBearDraw");
myDir.mkdirs();
File file = new File (myDir, name+".jpg");
if (file.exists ()) file.delete ();
try
{
if(!file.exists())
{
file.createNewFile();
}
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 50, ostream);
ostream.flush();
ostream.close();
mv.invalidate();
}
catch (Exception e)
{
e.printStackTrace();
}finally
{
mv.setDrawingCacheEnabled(false);
}
}
});
editalert.show();
}
private static final int COLOR_MENU_ID = Menu.FIRST;
private static final int EMBOSS_MENU_ID = Menu.FIRST + 1;
private static final int BLUR_MENU_ID = Menu.FIRST + 2;
private static final int ERASE_MENU_ID = Menu.FIRST + 3;
private static final int SRCATOP_MENU_ID = Menu.FIRST + 4;
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, COLOR_MENU_ID, 0, "Color").setShortcut('3', 'c');
menu.add(0, EMBOSS_MENU_ID, 0, "Emboss").setShortcut('4', 's');
menu.add(0, BLUR_MENU_ID, 0, "Blur").setShortcut('5', 'z');
menu.add(0, ERASE_MENU_ID, 0, "Erase").setShortcut('5', 'z');
menu.add(0, SRCATOP_MENU_ID, 0, "SrcATop").setShortcut('5', 'z');
/**** Is this the mechanism to extend with filter effects?
Intent intent = new Intent(null, getIntent().getData());
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
menu.addIntentOptions(
Menu.ALTERNATIVE, 0,
new ComponentName(this, NotesList.class),
null, intent, 0, null);
*****/
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
mPaint.setXfermode(null);
mPaint.setAlpha(0xFF);
switch (item.getItemId()) {
case COLOR_MENU_ID:
new ColorPickerDialog(FingerPaintActivity.this, this, mPaint.getColor()).show();
return true;
case EMBOSS_MENU_ID:
if (mPaint.getMaskFilter() != mEmboss) {
mPaint.setMaskFilter(mEmboss);
} else {
mPaint.setMaskFilter(null);
}
return true;
case BLUR_MENU_ID:
if (mPaint.getMaskFilter() != mBlur) {
mPaint.setMaskFilter(mBlur);
} else {
mPaint.setMaskFilter(null);
}
return true;
case ERASE_MENU_ID:
mPaint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.CLEAR));
return true;
case SRCATOP_MENU_ID:
mPaint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.SRC_ATOP));
mPaint.setAlpha(0x80);
return true;
}
return super.onOptionsItemSelected(item);
}
}
i have created live wallpaper using canvas now i want to add the layout like(relative layout)
if its possible?
in live wallpaper we can able to use layout?
please guide me how to add layout here if its possible?
if possible means how can i called that layout in my canvas class?
in this canvas how can i overwrite the ondraw mathod?
i have searched hole internet i can't able to fine any information.
i'm new to android live wallpaper and jave plz guide me.
here is my code
public class AquariumWallpaperService extends WallpaperService {
private float mTouchX = -1;
private float mTouchY = -1;
int count = 1;
public AquaticAnimal animal;
public static final String SHARED_PREFS_NAME = "livewallpapertemplatesettings";
#Override
public Engine onCreateEngine() {
return new AquariumWallpaperEngine();
}
class AquariumWallpaperEngine extends Engine {
private Aquarium aquarium;
public AquariumWallpaperEngine() {
this.aquarium = new Aquarium();
this.aquarium.initialize(getBaseContext(), getSurfaceHolder());
}
#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 onVisibilityChanged(boolean visible) {
if (visible) {
this.aquarium.render();
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
this.aquarium.start();
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
this.aquarium.stop();
}
}
this is my canvas class
public class Aquarium {
private AquariumThread aquariumThread;
private SurfaceHolder surfaceHolder;
private ArrayList<Renderable> fishes;
private Bitmap backgroundImage, backgroundImage1;
private Bitmap boble;
public Boolean bgchange = false;
private Context context;
public int count = 1, x = 100, y = 500, x1 = 400, y1 = 500, x2 = 10,
y2 = 250;
public AquariumWallpaperEngine aqua;
public void render() {
Canvas canvas = null;
try {
count++;
if (count > 5) {
if (count % 8 == 0) {
x2++;
y--;
y1--;
}
}
if (y == -20) {
y = 600;
y1 = 600;
}
if (x2 == 700) {
x2 = -20;
}
if (count > 3000) {
bgchange = true;
}
if (count > 6000) {
bgchange = false;
count = 0;
}
//System.out.println("count" + count);
canvas = this.surfaceHolder.lockCanvas(null);
synchronized (this.surfaceHolder) {
this.onDraw(canvas);
}
} finally {
if (canvas != null) {
this.surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this.fishes) {
renderable.render(canvas);
}
};
public void start() {
this.aquariumThread.switchOn();
}
public void stop() {
boolean retry = true;
this.aquariumThread.switchOff();
while (retry) {
try {
this.aquariumThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int getLeft() {
return 0;
}
public int getRight() {
return this.backgroundImage.getWidth();
}
public int getRightbg() {
return this.backgroundImage1.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.aquariumThread = new AquariumThread(this);
this.surfaceHolder = surfaceHolder;
this.fishes = new ArrayList<Renderable>();
this.context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.backgroundImage = BitmapFactory.decodeResource(
context.getResources(), com.thinkpal.live.R.drawable.aquarium,
options);
this.backgroundImage1 = BitmapFactory.decodeResource(
context.getResources(), com.thinkpal.live.R.drawable.waquarium,
options);
this.boble = BitmapFactory.decodeResource(context.getResources(),
com.thinkpal.live.R.drawable.bubble, options);
this.addFishes();
}
private void addFishes() {
Point startPoint = new Point(100, 100);
this.fishes.add(new ClownFish(this.context, this, startPoint, 90));
Point startPoint1 = new Point(100, 300);
this.fishes.add(new ClownFish(this.context, this, startPoint1, 50));
Point startPoint2 = new Point(200, 200);
this.fishes.add(new ClownFish(this.context, this, startPoint2, 15));
}
private void renderBackGround(Canvas canvas) {
Paint paint = new Paint();
canvas.drawBitmap(this.backgroundImage, 0, 0, null);
if (bgchange) {
canvas.drawBitmap(this.backgroundImage1, 0, 0, null);
}
canvas.drawBitmap(this.boble, x, y, null);
canvas.drawBitmap(this.boble, x1, y1, null);
canvas.drawBitmap(this.boble, x2, y2, null);
canvas.drawText("Think palm", x + 10, y + 45, paint);
canvas.drawText("Cochin", x1 + 20, y1 + 45, paint);
canvas.drawText("Welcome to", x2 + 10, y2 + 45, paint);
}
}
YOu could always call getTheme() in WallpaperService and then apply layouts to that, not sure what use it will be to you though. It looks like you've already got everything working, wouldn't really bother with layouts if I were you...