Draw multiple rectangles with delays between them - java

I am using Handler post delay to call onDraw each time I want to draw new rectangle, but for every new rectangle erase the previous one ..
How can I make the canvas keep the content of all rectangles:
My code:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.CountDownTimer;
import android.os.Handler;
import android.util.Log;
import com.adhamenaya.microchart.model.ChartData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
/**
* Created by Admin on 18/12/2016.
*/
public class ColumnChart extends Chart implements Runnable {
private int mSpace = 0;
private int mColumnSize = 0;
private int mColumnsCount = 0;
private int mCurrentStart = 0;
private float mHeightUnit = 0;
private int mHeightDiff;
int columnIndex = 0;
private Handler mHandler;
private Canvas mCanvas;
private Iterator mDataIterator;
static final long FRAME_TIME = 100;
private ArrayList<Rect> rectangles = new ArrayList<Rect>();
public ColumnChart(Context context) {
super(context);
mHandler = new Handler();
}
#Override
protected void prepare() {
if (mChartData != null && mChartData.getSingleData().size() > 0) {
mColumnsCount = mChartData.getSingleData().size();
// Column size, 1 is added to reserve a space at the end of the chart
mColumnSize = (int) ((mWidth / (mColumnsCount)) * 0.9);
// Calculate the space between the bars
mSpace = (mWidth / mColumnsCount) - mColumnSize;
// Calculate height unit
// Calculate 80% of the total height
float height08 = mHeight * 0.8f;
mHeightUnit = height08 / mChartData.getMax();
// Draw bars
mDataIterator = mChartData.getSingleData().entrySet().iterator();
mMainPaint = getRectPaint();
// Create rect objects
while (mDataIterator.hasNext()) {
Map.Entry entry = (Map.Entry) mDataIterator.next();
int columnHeight = (int) ((int) entry.getValue() * mHeightUnit);
String key = (String) entry.getKey();
// Shift the
mCurrentStart += mSpace;
// Calculate the difference between the total height and the height of the column
mHeightDiff = mHeight - columnHeight;
mCurrentStart += mColumnSize;
mDataIterator.remove();
Rect rect = new Rect(mCurrentStart, mHeightDiff,
mCurrentStart + mColumnSize, mHeight);
rectangles.add(rect);
}
}
}
#Override
protected void paintChart(Canvas canvas) {
}
#Override
public void setData(ChartData data) {
this.mChartData = data;
prepare();
mHandler.post(this);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Get measured height and width of the view
setMeasuredDimension(getMeasurement(widthMeasureSpec, mWidth),
getMeasurement(heightMeasureSpec, mHeight));
// mWidth = MeasureSpec.getSize(widthMeasureSpec);
// mHeight = MeasureSpec.getSize(heightMeasureSpec);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(columnIndex > 0 && columnIndex<rectangles.size())
canvas.drawRect(rectangles.get(columnIndex), getRectPaint());
}
#Override
public void run() {
if(columnIndex<rectangles.size()){
invalidate();
columnIndex++;
mHandler.postDelayed(this,FRAME_TIME);
}else{
mHandler.removeCallbacks(this);
}
}
}

Create a FrameLayout on which you want to draw rectangles. Create a view every time you are drawing a new circle. Draw circle on newly created view and the add that view to FrameLayout. Background of the view will be transparent by default. If not then set the background as transparent. This way your previous rectangles will be visible and new rectangle will be drawn on existing rectangles.

Your are near to make it done! Just call you prepare after calling invalidate method.
#Override
public void run() {
if(columnIndex<rectangles.size()){
invalidate();
columnIndex++;
mHandler.postDelayed(this,FRAME_TIME);
}else{
mHandler.removeCallbacks(this);
eraseAll();
}
}
...
public void eraseAll() {
this.canvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
prepare();
}

For me this logic is working fine
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(columnIndex < rectangles.size()) {
for (int i = 0; i <= columnIndex; ++i) {
canvas.drawRect(rectangles.get(i), paint);
}
}
}

Simplest heck is to keep the canvas object as class level variable and always draw on this canvas object and in super.onDraw() pass on this canvas, it will always keep your previous rectangles drawn

Related

How to load sprite sheet with 5 rows and 5 columns top view in android?

I have a sprite sheet of 612x864 dimension with 5 rows and 5 columns .My problem is how can I load it and animate it? I want to move the cat sprite in y-axis only .I've already try but my code is not working properly. Here is my code.
In GameView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
private Bitmap bmp;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private Sprite sprite;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.catsprite);
sprite = new Sprite(this,bmp);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
sprite.onDraw(canvas);
}
}
GameLoopThread.java
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
static final long FPS = 10;
private GameView view;
private boolean running = false;
public GameLoopThread(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
Sprite.java
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Sprite {
private static final int BMP_ROWS = 5;
private static final int BMP_COLUMNS = 5;
private int x = 0;
private int y = 0;
private int ySpeed = 3;
private GameView gameView;
private Bitmap bmp;
private int currentFrame = 1;
private int width;
private int height;
public Sprite(GameView gameView, Bitmap bmp) {
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
}
private void update() {
if (y > gameView.getWidth() - width - y) {
ySpeed = -5;
}
if (y + y < 0) {
ySpeed = 5;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = 1 * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
}
I'll recommend you to use this library. It's great for Sprite Animation. It has some limitations though, but it works fine.
Here is the code how I done it.
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.runningcat);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int frameWidth = width / 5; //you have 5 columns
int frameHeight = height / 5; //and 5 rows
int frameNum = 25; //there would be 25 images
SpriteSheetDrawer spriteSheetDrawer = new SpriteSheetDrawer(
bitmap,
frameWidth,
frameHeight,
frameNum)
.spriteLoop(true)
.frequency(2); //change it as per your need
DisplayObject displayObject = new DisplayObject();
displayObject
.with(spriteSheetDrawer)
.tween()
.tweenLoop(true)
.transform(0, 0) //I have changed it according to my need, you can also do this by changing these values
.toX(4000, 0) //this one too.
.end();
//In actual example, it's set as animation starts from one end of the screen and goes till the other one.
FPSTextureView textureView = (FPSTextureView) findViewById(R.id.fpsAnimation);
textureView.addChild(displayObject).tickStart();
Problem is in src value that you're using in method. canvas.drawBitmap(bmp, src, dst, null); srcY should be zero. I've tested here.
private Bitmap character;
private counter,charFrame;
private RectF annonymousRectF;
private Rect annonymousRect;
public Sprite() {
character=BitmapFactory.decodeResource(context.getResources(), R.drawable.flipchar2);
annonymousRect=new Rect();
annonymousRectF=new RectF();
}
public void update() {
counter++;
if(counter%5==0)
if(charFrame<NO_CHAR_FRAME-1)
charFrame++;
else
charFrame=0;
}
public void draw(){
annonymousRect.set(charFrame*character.getWidth()/NO_CHAR_FRAME,0,(charFrame+1)*character.getWidth()/NO_CHAR_FRAME,character.getHeight());
annonymousRectF.set(-width*.015f,height*.35f,width*.5f,height*.58f); //set value according to where you want to draw
canvas.drawBitmap(character, annonymousRect,annonymousRectF, null);
}

Moving Rectangle Up the Screen

I have a rectangle I want to move up the screen at a constant rate and am confused as to why my code isn't working. Below is the code:
package com.ashmore.MyGame;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
import com.ashmore.framework.Game;
import com.ashmore.framework.Graphics;
import com.ashmore.framework.Image;
import com.ashmore.framework.Screen;
import com.ashmore.framework.Input.TouchEvent;
public class GameScreen extends Screen {
enum GameState {
Ready, Running, Paused
}
GameState state = GameState.Ready;
boolean BarisMoving = false;
private ArrayList<Rect> rectangles = new ArrayList<Rect>();
int bar_x = 32;
int bar_y = 653;
int bar_width = 183;
int bar_height = 648;
Rect bar;
Paint paint;
public GameScreen(Game game) {
super(game);
// Initialize game objects here
bar = new Rect();
bar.set(bar_x, bar_y, bar_width, bar_height);
// Defining a paint object
paint = new Paint();
paint.setTextSize(30);
paint.setTextAlign(Paint.Align.CENTER);
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
}
private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
// 1. All touch input is handled here:
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
BarisMoving = true;
if (event.type == TouchEvent.TOUCH_UP) {
if (ScalesScreen.scaleType.equals("C")) {
rectangles.add(new Rect(56, 400, 80, 435));
//rectangles.get(0);
break;
}
if (BarisMoving) {
bar_y = bar_y -= 10;
}
for (Rect rect : rectangles) {
if(bar.intersect(rect)) {
checkButtons();
}
}
}
}
private void checkButtons() {
Log.d("GameScreen","Note and Bar Intersected");
}
#Override
public void paint(float deltaTime) {
Graphics g = game.getGraphics();
Paint paint = new Paint();
Paint paint2 = new Paint();
paint.setColor(Color.RED);
paint2.setColor(Color.RED);
for (Rect rect : rectangles) {
g.drawRect(rect, paint);
}
g.drawRect(bar, paint2);
}
private boolean inBounds(TouchEvent event, int x, int y, int width,
int height) {
if (event.x > x && event.x < x + width - 1 && event.y > y
&& event.y < y + height - 1)
return true;
else
return false;
}
}
I am probably missing something really basic. However, I can't seem to find the issue. Any help is appreciated!
I have figured out my problem. The problem was where my code was placed in the updateRunning() method. In my question, the setting of the boolean BarisMoving was set equal to "true" when there was a touch event:
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
BarisMoving = true;
The boolean had to be moved outside of this (above int len = touchEvents.size();) and outside of the whole touch event area to work the way I wanted (outside of the for () { and the ending bracket }).

Android : moving bmp leaving a trail ( Surface View and Canvas )

I was trying to animate a sprite for an android app and i've encounter a small problem. I'm drawing on a surfaceView that i add on top of already existing layouts. On this surfaceView, i wanted to animate few sprites so they would walk along a path.
So this is the result i'm facing right now :
The walking sprite is leaving a trail. So i decided to google this problem and apparently i had to clear the canvas first before drawing on it.
This was my onDraw method before :
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
And this was my onDraw method after
public void onDraw(Canvas canvas) {
canvas.drawRGB(0, 0, 0);
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
So i now have this as a result
which is great because it leaves no more trail BUT i cant see the layouts underneath. Is there anyway i can get the best of both world ? I thought clearing the canvas would work but it obviously doesnt not work as expected.
I'll post my code below
SurfaceView :
public class MonsterView extends SurfaceView {
private Bitmap monsterImg;
private SurfaceHolder holder;
private MonsterThread mainThread;
private Sprite monsterSprite;
private int x;
private int xSpeed = 1;
public MonsterView(Context context) {
super(context);
this.mainThread = new MonsterThread(this);
this.x = 0;
holder = getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
mainThread.setRunning(true);
mainThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mainThread.setRunning(false);
while (retry) {
try {
mainThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
});
setZOrderOnTop(true);
monsterImg = BitmapFactory.decodeResource(getResources(), R.drawable.fire);
monsterSprite = new Sprite(this,monsterImg);
}
#Override
public void onDraw(Canvas canvas) {
if (x == getWidth() - monsterImg.getWidth()) {
xSpeed = -1;
}
if (x == 0) {
xSpeed = 1;
}
x = x + xSpeed;
monsterSprite.onDraw(canvas);
}
Thread :
public class MonsterThread extends Thread {
private MonsterView monsterSurface;
private boolean running;
static final long FPS = 35;
public MonsterThread(MonsterView monsterSurface){
this.monsterSurface = monsterSurface;
this.running = false;
}
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while(running){
Canvas c = null;
startTime = System.currentTimeMillis();
try{
c = monsterSurface.getHolder().lockCanvas();
synchronized (monsterSurface.getHolder()){
monsterSurface.onDraw(c);
}
} finally {
if( c!= null){
monsterSurface.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if(sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e){}
}
}
public MonsterView getMonsterSurface() {
return monsterSurface;
}
public void setMonsterSurface(MonsterView monsterSurface) {
this.monsterSurface = monsterSurface;
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
Sprite :
public class Sprite {
private static final int BMP_ROWS = 4;
private static final int BMP_COLUMNS = 3;
private int x = 0;
private int y = 0;
private int xSpeed = 5;
private MonsterView monsterView;
private Bitmap bmp;
private int currentFrame = 0;
private int width;
private int height;
private int directionX;
public Sprite(MonsterView monsterView, Bitmap bmp) {
this.monsterView = monsterView;
this.bmp=bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
this.directionX = 2;
}
private void update() {
if (x > monsterView.getWidth() - width - xSpeed) {
xSpeed = -5;
directionX = 1;
}
if (x + xSpeed < 0) {
xSpeed = 5;
directionX = 2;
}
x = x + xSpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
Log.d("test", ""+currentFrame);
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
You're using setZOrderOnTop(), which is putting the Surface part of the SurfaceView on a layer above everything else. (By default, it's a separate layer below everything else.) When you clear it with canvas.drawRGB(0, 0, 0) you're setting the entire layer to opaque black, which is going to obscure the View layer beneath it.
If instead you clear it to transparent black, with canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR), you should get the results you want.
FWIW, you shouldn't override onDraw() if you're only drawing on the Surface. The onDraw() method is called by the View hierarchy to draw on the View part of the SurfaceView. If something manages to invalidate the SurfaceView's View, your onDraw() will be called, and you'll end up with a character sprite on the View layer. (Depending on your layout this may not be visible.) Just give the method a different name.
There are a number of ways to handle this, but generally, the way to do this is by maintaining a background layer (which is just another image), and sprite layers. Instead of clearing, at each frame you blit (copy) your background onto the surface (which erases everything), then you blit your sprites.
So you're going to have to draw the background bitmap onto the surface first before drawing your sprite. Right now you're drawing black which is covering your background layouts.
Alternatively you might be able to do canvas.drawRect with a Paint with paint.setColor to Color.Transparent.

How to make rect object inside SurfaceView clickable (setOnItemClickListener)

I am making some kind of a puzzle game, where there are blocks and the user has to click on it to move the blocks, and I need to setOnItemClickListener on each individual block(rect object) as each block will act differently when clicked based on its position. Now I have managed to draw the blocks, but I am not able to add item click listener to each different blocks.
MainActivity.java
public class MainActivity extends Activity {
PuzzleView puzzleView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get a display object to access screen details
Display display = getWindowManager().getDefaultDisplay();
// Load the resolution into a Point object
Point size = new Point();
display.getSize(size);
// Initialize gameView and set it as the view
puzzleView = new PuzzleView(this, size.x, size.y);
setContentView(puzzleView);
}
// This method executes when the player starts the game
#Override
protected void onResume() {
super.onResume();
// Tell the gameView resume method to execute
puzzleView.resume();
}
}
PuzzleView.java
public class PuzzleView extends SurfaceView implements Runnable {
Context context;
// This is our thread
private Thread gameThread = null;
// Our SurfaceHolder to lock the surface before we draw our graphics
private SurfaceHolder ourHolder;
// A boolean which we will set and unset
// When the game is running or not
private volatile boolean playing;
// Game is paused at the start
private boolean paused = true;
// A canvas and a Paint object
private Canvas canvas;
private Paint paint;
// Size of screen in pixels
private int screenX;
private int screenY;
// Blocks of puzzle
private Block[] blocks = new Block[10];
private int numBlocks;
// Position of block
private int block_right;
// When we initialize call on gameView
// This constructor runs
public PuzzleView(Context context, int x, int y) {
// Ask SurfaceView class to set up our object
super(context);
// Make a globally available copy of the context so we can use it in another method
this.context = context;
// Initialize ourHolder and paint objects
ourHolder = getHolder();
paint = new Paint();
screenX = x;
screenY = y;
block_right = 0;
prepareLevel();
}
private void prepareLevel() {
// Here we will intialize all game objects
// Build the blocks
numBlocks = 0;
for(int column = 0; column < 2; column++) {
for(int row = 0; row < 2; row++) {
blocks[numBlocks] = new Block(row, column, screenX, screenY);
numBlocks++;
}
}
}
#Override
public void run() {
while(playing) {
// Update the frame
if(!paused) {
update();
}
// Draw the frame
draw();
}
}
private void update() {
// Move the block
}
private void draw() {
// Make sure our drawing surface is valid or we crash
if(ourHolder.getSurface().isValid()) {
// Lock the canvas ready to draw
canvas = ourHolder.lockCanvas();
// Draw the background color
canvas.drawColor(Color.argb(255, 255, 255, 255));
// Choose the brush color for drawing
paint.setColor(Color.RED);
// Draw the block
for(int i = 0; i < numBlocks; i++) {
canvas.drawRect(blocks[i].getRect(), paint);
}
//Change brush color for text
paint.setColor(Color.BLACK);
// Draw the score
paint.setTextSize(20);
canvas.drawText("Right: " + block_right, 10, screenY - 50, paint);
// Draw everything to the screen
ourHolder.unlockCanvasAndPost(canvas);
}
}
// If MainActivity is started then start our thread
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
}
Block.java
public class Block {
private RectF rect;
public Block(int row, int column, int screenX, int screenY) {
int padding = 1;
int width = 50;
int height = 50;
int outer_padding = (screenX - 104) / 2;
rect = new RectF(column * width + padding + outer_padding,
row * height + padding + 40,
column * width + width - padding + outer_padding,
row * height + height - padding + 40);
}
public RectF getRect() {
return this.rect;
}
}
Now how do I make a click event listener to each block object ?
All suggestions and improvements are greatly welcomed.
Thanks in advance.
You can't add listeners to drawn objects. The listeners are for separate views.
If you do want to draw everything by yourself, you can still determine if a touch event happened inside of your rectangle:
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Check if click is within bounds of your rect
if (event.getX() >= mRectStartX && event.getX() <= mRectEndX && event.getY() >= mRectStartY && event.getY() <= mRectEndY) {
// Clicked within your rect, register further clicks by consuming this click
return true;
}
}
return super.onTouchEvent(event);
}
You'll have to re-draw your rectangle once the touch is detected.
This is much more complicated than a simple click listener but that's what you get for wanting to draw on your own :P
P.S. you can use GestureDetector to simplify this process, but essentially it stays the same.

ListField display image from URL

I am displaying a customized list field with text on the right side and image on the left side.The image comes from a URL dynamically. Initially i am placing a blank image on the left of the list field,then call URLBitmapField class's setURL method,which actually does the processing and places the processed image on top of the blank image.The image gets displayed on the list field,but to see that processed image i need to click on the list field image.I want the processed image to be displayed automatically in the list field after the processing.Can anyone tell me where i am getting wrong?I have been asking for help,but no one seems to figure out the problem.Any productive suggestions would be appreciated
import java.util.Vector;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.component.NullField;
import net.rim.device.api.ui.container.FullScreen;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.util.Arrays;
import net.rim.device.api.ui.component.ListField;
public class TaskListField extends UiApplication {
// statics
// ------------------------------------------------------------------
public static void main(String[] args) {
TaskListField theApp = new TaskListField();
theApp.enterEventDispatcher();
}
public TaskListField() {
pushScreen(new TaskList());
}
}
class TaskList extends MainScreen implements ListFieldCallback {
private Vector rows;
private Bitmap p1;
private Bitmap p2;
private Bitmap p3;
String Task;
ListField listnew = new ListField();
private VerticalFieldManager metadataVFM;
TableRowManager row;
public TaskList() {
super();
URLBitmapField artistImgField;
listnew.setRowHeight(80);
listnew.setCallback(this);
rows = new Vector();
for (int x = 0; x <3; x++) {
row = new TableRowManager();
artistImgField = new URLBitmapField(Bitmap
.getBitmapResource("res/images/bg.jpg"));
row.add(artistImgField);
String photoURL = "someimagefrmurl.jpg";
Log.info(photoURL);
// strip white spaces in the url, which is causing the
// images to not display properly
for (int i = 0; i < photoURL.length(); i++) {
if (photoURL.charAt(i) == ' ') {
photoURL = photoURL.substring(0, i) + "%20"
+ photoURL.substring(i + 1, photoURL.length());
}
}
Log.info("Processed URL: " + photoURL);
artistImgField.setURL(photoURL);
LabelField task = new LabelField("Display");
row.add(task);
LabelField task1 = new LabelField(
"Now Playing" + String.valueOf(x));
Font myFont = Font.getDefault().derive(Font.PLAIN, 12);
task1.setFont(myFont);
row.add(task1);
rows.addElement(row);
}
listnew.setSize(rows.size());
this.add(listnew);
//listnew.invalidate();
}
// ListFieldCallback Implementation
public void drawListRow(ListField listField, Graphics g, int index, int y,
int width) {
TableRowManager rowManager = (TableRowManager) rows.elementAt(index);
rowManager.drawRow(g, 0, y, width, listnew.getRowHeight());
}
protected void drawFocus(Graphics graphics, boolean on) {
}
private class TableRowManager extends Manager {
public TableRowManager() {
super(0);
}
// Causes the fields within this row manager to be layed out then
// painted.
public void drawRow(Graphics g, int x, int y, int width, int height) {
// Arrange the cell fields within this row manager.
layout(width, height);
// Place this row manager within its enclosing list.
setPosition(x, y);
// Apply a translating/clipping transformation to the graphics
// context so that this row paints in the right area.
g.pushRegion(getExtent());
// Paint this manager's controlled fields.
subpaint(g);
g.setColor(0x00CACACA);
g.drawLine(0, 0, getPreferredWidth(), 0);
// Restore the graphics context.
g.popContext();
}
// Arrages this manager's controlled fields from left to right within
// the enclosing table's columns.
protected void sublayout(int width, int height) {
// set the size and position of each field.
int fontHeight = Font.getDefault().getHeight();
int preferredWidth = getPreferredWidth();
// start with the Bitmap Field of the priority icon
Field field = getField(0);
layoutChild(field, 146,80);
setPositionChild(field, 0, 0);
// set the task name label field
field = getField(1);
layoutChild(field, preferredWidth - 16, fontHeight + 1);
setPositionChild(field, 149, 3);
// set the list name label field
field = getField(2);
layoutChild(field, 150, fontHeight + 1);
setPositionChild(field, 149, fontHeight + 6);
setExtent(360, 480);
}
// The preferred width of a row is defined by the list renderer.
public int getPreferredWidth() {
return listnew.getWidth();
}
// The preferred height of a row is the "row height" as defined in the
// enclosing list.
public int getPreferredHeight() {
return listnew.getRowHeight();
}
}
public Object get(ListField listField, int index) {
// TODO Auto-generated method stub
return null;
}
public int getPreferredWidth(ListField listField) {
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
// TODO Auto-generated method stub
return 0;
}
}
Finally i solved it of my own. This worked:
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
listnew.invalidate();
}
},500,true);

Categories

Resources