Animation flashing - animation

I continuously have this problem with all my most recent animation projects. Every time I run my animations, they never seem to be completely visible and full, but rather they blink and flash similar to a light bulb that is not fully screwed in ( i know, strange comparison but I can't think of what else it resembles). I feel like it must have something to do with my placement of repaint(); but I'm just not sure at this point. On a previous animation I made, the problem was that my "private BufferedImage offScr" variable wasn't set correctly, but viewing other programs similar to the one I am working on now, I don't see why that variable would be necessary. Thanks for all your help folks, and I apologize for my lack of knowledge in programming vocabulary.
Here is my program so far:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
public class DoveAnimator extends JFrame implements ActionListener {
private int DELAY = 40; // the delay for the animation
private final int WIDTH = 400; // the window width
private final int HEIGHT = 180; // the window height
private final int IMAGEAMT = 8;
private Image [] doveLeft = new Image[IMAGEAMT];
private Image [] doveRight = new Image[IMAGEAMT];
private int doveIndex = 0;
private boolean isRight = true;
private JPanel dovePanel;
private Image dove;
private JButton slowerButton = new JButton ("Slower");
private JButton fasterButton = new JButton ("Faster");
private JButton reverseButton = new JButton ("Reverse");
private JButton pauseResumeButton = new JButton (" pause ");
private Timer timer;
private int clicks = 2;
private boolean pause = false;
/** The constructor */
public DoveAnimator() {
MediaTracker track = new MediaTracker(this);
for (int i = 0; i < IMAGEAMT; ++i) {
doveLeft[i] = new ImageIcon("doves/ldove" + (i+1) + ".gif").getImage();
doveRight[i] = new ImageIcon("doves/rdove" + (i+1) + ".gif").getImage();
track.addImage(doveLeft[i],0);
track.addImage(doveRight[i],0);
}
// dove = doveRight[0];
//track.addImage(bkgImage,0);
// track.addImage(dove,0);
try {
track.waitForAll();
} catch ( InterruptedException e ) { }
dove = doveRight[0];
JPanel mainPanel = new JPanel();
mainPanel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
setTitle ("Dove Animator");
dovePanel = new JPanel();
dovePanel.setPreferredSize(new Dimension(100, 125));
dovePanel.setBackground(Color.WHITE);
mainPanel.add(dovePanel);
JPanel buttonPanel = new JPanel();
buttonPanel.setPreferredSize(new Dimension(WIDTH, 40));
// button 1
slowerButton.addActionListener (this);
buttonPanel.add (slowerButton);
// button 2
fasterButton.addActionListener (this);
buttonPanel.add (fasterButton);
// button 3
reverseButton.addActionListener (this);
buttonPanel.add (reverseButton);
// button 4
pauseResumeButton.addActionListener (this);
buttonPanel.add (pauseResumeButton);
mainPanel.add(buttonPanel);
add(mainPanel);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setVisible (true);
pack();
timer = new Timer(DELAY,this); // setting timer delay
timer.start(); // start the timer
}
public void switchDove() {
++doveIndex;
if (doveIndex >= IMAGEAMT)
doveIndex = 0;
if (isRight)
dove = doveRight[doveIndex];
else
dove = doveLeft[doveIndex];
dove = (isRight) ? doveRight[doveIndex] : doveLeft[doveIndex];
}
/** Handler for button clicks and timer events */
public void actionPerformed (ActionEvent evt) {
if (evt.getSource() == slowerButton)
{
DELAY += 10;
}
else if (evt.getSource() == reverseButton)
{
if(evt.getSource() == reverseButton && isRight == true){
isRight = false;
}
else if(evt.getSource() == reverseButton && !isRight){
isRight = true;
}
}
else if (evt.getSource() == fasterButton)
{
DELAY -= 10;
if (DELAY <= 10 ){
DELAY = 10;
}
}
else if (evt.getSource() == pauseResumeButton)
{
if(evt.getSource() == pauseResumeButton && !pause){
pauseResumeButton.setText(" Resume ");
timer.stop();
pause = true;
}
else if(evt.getSource() == pauseResumeButton && pause == true){
pauseResumeButton.setText(" Pause ");
timer.start();
pause = false;
}
}
else if (evt.getSource() == timer)
{
drawAnimation();
switchDove();
repaint();
}
}
/** Draws the dove in the dovePanel */
public void drawAnimation() {
Graphics page = dovePanel.getGraphics();
page.drawImage(dove,0,0,Color.WHITE,null);
}
/** The main method */
public static void main (String [] args) {
new DoveAnimator();
}
}

Yep it seems to be one of your repaint() calls. Take out your repaint() method call here:
else if (evt.getSource() == timer)
{
drawAnimation();
switchDove();
repaint();
It's confusing the program because you are already switching the doves. That's my best guess. I ran it and it seems to work though. Cheers!

Also I just noticed that the way you are adjusting your timer will yeild you no results. You need to use the command: timer.setDelay(newDelay); you can also put arguments in the parenthesis like timer.setDelay(DELAY -= 10);

Related

How to create a restart method using JFrame?

recently I started learning Java, I watched a YT video where a programmer used static methods and variables to create a simple guess game using JFrame.
Afterwards I tried to implement a close/restart button, after reading some Threads I relized static methods arenĀ“t made that for. So my question is now how do I solve my problem now. :)
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ThreadLocalRandom;
public class main extends JFrame {
JLabel text = new JLabel("Please choose a number between 1 & 10 ");
JLabel textVersuch = new JLabel();
JButton button = new JButton("Try");
int myNumber = ThreadLocalRandom.current().nextInt(1,10+1);
JTextField textField = new JTextField();
int count = 0;
//is there a better way to hide all this information, but still keep them useable for my methods?
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.openUI(); //error occurs
}
//How do I manage to start my method openUI() to start my game?
public void openUI(){
JFrame frame = new JFrame("Program");
frame.setSize(400,400);
frame.setLocation(800,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setDefaultLookAndFeelDecorated(true);
text.setBounds(0,50,400,25);
textVersuch.setBounds(300,0,100,25);
textField.setBounds(0,150,50,25);
button.setBounds(50,150,100,25);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
String textFromTextfield = textField.getText();
int number = Integer.parseInt(textFromTextfield);
if(number<1 || number>10){
text.setText("Your number has to be between 1 & 10 ");
textField.setText("");
}else{
guess(number);
}
}catch (Exception error){
text.setText("Please enter a digit! ");
textField.setText("");
}
}});
frame.add(button);
frame.add(textField);
frame.add(text);
frame.add(textVersuch);
frame.setLayout(null);
frame.setVisible(true);
}
public void close(JFrame frame){
frame.dispose(); //here I want to close the game
}
public void guess(int number ) throws InterruptedException {
count++;
textVersuch.setText(count + " tries!");
if(number == myNumber){
text.setText("You was right! " + " You tried " + count + " time(s) :)" );
button.setText("Restart");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//How can I restart my JFrame?
}
});
} else if (count < 3) {
text.setText("Wrong guess! Retry");
if (number < myNumber){
text.setText("Your searched number is bigger than" + number );
}else {
text.setText("Your searched number is lower than" + number );
}
} else {
text.setText("Sorry, you lost the number was " + myNumber);
}
textField.setText("");
}
}

JavaFX Move image animation

How would I move an image across an AnchorPane in JavaFX? The image should move itself over a period of time. So far I have: (view is the ImageView already in the AnchorPane)
position = 35.0;
for(int x = 0; x<11; x++){
TimeUnit.SECONDS.sleep(1);
myAnchorPane.getChildren().remove(view);
AnchorPane.setRightAnchor(view, position);
AnchorPane.setTopAnchor(view, 103.0);
myAnchorPane.getChildren().add(view);
position += 20;
}
within the initialize() method of my controller. However, this does not work since the stage appears with the image already moved.
Here is a class I create from an idea I got from tutoring a student.
You should use Javafx animation. This moves with button press, but if you
want to see the diver move right, just remove the code from inside the isRightPressed if-statement and place it outside the if-statement. Also, remove this part: * (Math.cos(Math.toRadians(rotation))).
import java.io.File;
import javafx.animation.AnimationTimer;
import javafx.event.EventHandler;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
/**
*
* #author blj0011
*/
public class Diver {
File diverFile;
ImageView ivDiver = new ImageView();
double rotation = 0.0;
boolean isUpPressed, isDownPressed, isLeftPressed, isRightPressed;
Diver()
{
diverFile = new File("src/img/diver.png");
if(diverFile.exists())
{
Image diverImage = new Image(diverFile.toURI().toString());
ivDiver.setImage(diverImage);
}
ivDiver.setFocusTraversable(true);
ivDiver.setOnKeyPressed(new EventHandler<KeyEvent>()
{
#Override
public void handle(KeyEvent event) {
switch(event.getCode()) {
case UP: isUpPressed = true; break;
case DOWN: isDownPressed = true; break;
case LEFT: isLeftPressed = true; break;
case RIGHT: isRightPressed = true; break;
}
}
});
ivDiver.setOnKeyReleased(new EventHandler<KeyEvent>()
{
#Override
public void handle(KeyEvent event) {
switch(event.getCode()) {
case UP: isUpPressed = false; break;
case DOWN: isDownPressed = false; break;
case LEFT: isLeftPressed = false; break;
case RIGHT: isRightPressed = false; break;
}
}
});
AnimationTimer timer = new AnimationTimer(){
#Override
public void handle(long now) {
if(isUpPressed){if(rotation == -360){rotation = 0;} ivDiver.setRotate(rotation+=5);}
if(isDownPressed){if(rotation == 360){rotation = 0;} ivDiver.setRotate(rotation-=5);}
if(isLeftPressed)
{
ivDiver.setX(ivDiver.getX() - 2.0 * (Math.cos(Math.toRadians(rotation))));
ivDiver.setY(ivDiver.getY() - 2.0 * (Math.sin(Math.toRadians(rotation))));
}
if(isRightPressed)
{
System.out.println("moving diver right!");
ivDiver.setX(ivDiver.getX() + 2.0 * (Math.cos(Math.toRadians(rotation))));
ivDiver.setY(ivDiver.getY() + 2.0 * (Math.sin(Math.toRadians(rotation))));
}
}
};
timer.start();
}
ImageView getDiver()
{
return ivDiver;
}
}
You code may look something like this.
AnimationTimer timer = new AnimationTimer(){
#Override
public void handle(long now) {
System.out.println("moving diver right!");
yourImageView.setX(yourImageView.getX() + 20.0 );
//yourImageView.setY(yourImageView.getY() + 20.0 );
}
};
timer.start();

How to scroll a Pager programatically AND smoothly

I'm using this code to scroll programatically my pager
public void MoveNext(View view) {
pager.setCurrentItem(pager.getCurrentItem() + 1);
}
public void MovePrevious(View view) {
pager.setCurrentItem(pager.getCurrentItem() - 1);
}
The code work perfect but the transition is too fast. How can I introduce a delay so that the scrolling would be done more smoothly?
I believe there are two ways can achieve this goal, I've tried by ViewPager's fakeDrag() but which doesn't work perfect, luckly, another way does, by simulate touch motion event and use ObjectAnimator to specify the animation duration then make control the scroll speed become true.
public class ViewPagerActivity extends FragmentActivity
implements View.OnClickListener, Animator.AnimatorListener {
private ViewPager mViewPager;
private View btnTriggerNext;
private View btnTriggerPrev;
#Override
protected void onCreate(...) {
super...;
setContentView(R.layout.layout_xml);
mViewPager = findViewById(...);
btnTriggerNext = findViewById(R.id.btnTriggerNext);
btnTriggerNext.setOnClickListener(this);
btnTriggerPrev = findViewById(R.id.btnTriggerPrev);
btnTriggerPrev.setOnClickListener(this);
}
private boolean mIsInAnimation;
private long mMotionBeginTime;
private float mLastMotionX;
#Override
public void onClick(View v) {
if (mIsInAnimation) return;
ObjectAnimator anim;
if (v == btnTriggerPrev) {
if (!hasPrevPage()) return;
anim = ObjectAnimator.ofFloat(this, "motionX", 0, mViewPager.getWidth());
}
else if (v == btnTriggerNext) {
if (!hasNextPage()) return;
anim = ObjectAnimator.ofFloat(this, "motionX", 0, -mViewPager.getWidth());
}
else return;
anim.setInterpolator(new LinearInterpolator());
anim.addListener(this);
anim.setDuration(300);
anim.start();
}
public void setMotionX(float motionX) {
if (!mIsInAnimation) return;
mLastMotionX = motionX;
final long time = SystemClock.uptimeMillis();
simulate(MotionEvent.ACTION_MOVE, mMotionBeginTime, time);
}
#Override
public void onAnimationEnd(Animator animation) {
mIsInAnimation = false;
final long time = SystemClock.uptimeMillis();
simulate(MotionEvent.ACTION_UP, mMotionBeginTime, time);
}
#Override
public void onAnimationStart(Animator animation) {
mLastMotionX = 0;
mIsInAnimation = true;
final long time = SystemClock.uptimeMillis();
simulate(MotionEvent.ACTION_DOWN, time, time);
mMotionBeginTime = time;
}
// method from http://stackoverflow.com/a/11599282/1294681
private void simulate(int action, long startTime, long endTime) {
// specify the property for the two touch points
MotionEvent.PointerProperties[] properties = new MotionEvent.PointerProperties[1];
MotionEvent.PointerProperties pp = new MotionEvent.PointerProperties();
pp.id = 0;
pp.toolType = MotionEvent.TOOL_TYPE_FINGER;
properties[0] = pp;
// specify the coordinations of the two touch points
// NOTE: you MUST set the pressure and size value, or it doesn't work
MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[1];
MotionEvent.PointerCoords pc = new MotionEvent.PointerCoords();
pc.x = mLastMotionX;
pc.pressure = 1;
pc.size = 1;
pointerCoords[0] = pc;
final MotionEvent ev = MotionEvent.obtain(
startTime, endTime, action, 1, properties,
pointerCoords, 0, 0, 1, 1, 0, 0, 0, 0);
mViewPager.dispatchTouchEvent(ev);
}
private boolean hasPrevPage() {
return mViewPager.getCurrentItem() > 0;
}
private boolean hasNextPage() {
return mViewPager.getCurrentItem() + 1 < mViewPager.getAdapter().getCount();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
}
cause it was simulating touch event, so please use a proper duration(less than 600ms will be nice) to do scrolling, when scroll in progress, put down finger would stop it and cause some bugs.
Change
pager.setCurrentItem(pager.getCurrentItem() + 1);
to
pager.setCurrentItem(pager.getCurrentItem() + 1,true);
This will call the method setCurrentItem(int item,boolean smoothScroll) which will scroll smoothly to the mentioned item instead of transitioning immediately

Adding animation to a button in BlackBerry

I want to use animation on a Button that I created in my BlackBerry App. The animation works fine the first time when I click the button. On first click, the button starts animation (blinking). On second click the blinking stops. However, when I click the button again (third time), the blinking should start again. However, I get an error:
App Error 104 Uncaught: IllegalStateException
The code for creating the Button and adding animation is as follows:
final Bitmap image000 = Bitmap.getBitmapResource("panic.png");
final Bitmap image001 = Bitmap.getBitmapResource("panicon.png");
final Timer animationTimer = new Timer();
final BitmapField animationField = new BitmapField(image000,BitmapField.FOCUSABLE){
protected boolean navigationClick(int status, int time)
{
if(flag){
animationTask.cancel();
flag=false;
}else{
animationTimer.scheduleAtFixedRate(animationTask, 0, 100);
flag=true;
}
return true;
}
};
animationTask = new TimerTask() {
public void run() {
if(counter == 0){
animationField.setBitmap(image000);
}
if(counter == 1){
animationField.setBitmap(image001);
counter = -1;
}
counter++;
}
};
add(animationField);
EDIT: I debugged my code and the error occurs in the loop that starts the thread. Cancelling the thread seems fine. I am lost what is the issue. Please guide.
try this -
TimerTask animationTask;
BitmapField animationField;
final Bitmap image000 = Bitmap.getBitmapResource("panic.png");
final Bitmap image001 = Bitmap.getBitmapResource("panicon.png");
final Timer animationTimer = new Timer();
animationField = new BitmapField(image000,BitmapField.FOCUSABLE){
protected boolean navigationClick(int status, int time)
{
if(flag){
animationTask.cancel();
flag=false;
}else{
animationTask = new TimerTask() {
public void run() {
if(counter == 0){
animationField.setBitmap(image000);
}
if(counter == 1){
animationField.setBitmap(image001);
counter = -1;
}
counter++;
}
};
animationTask.run();
animationTimer.scheduleAtFixedRate(animationTask, 0, 100);
flag=true;
}
return true;
}
};
animationTask = new TimerTask() {
public void run() {
if(counter == 0){
animationField.setBitmap(image000);
}
if(counter == 1){
animationField.setBitmap(image001);
counter = -1;
}
counter++;
}
};
add(animationField);

canvas.DrawBitmap() executing at onPostExecute in AsyncTask but Bitmap not displaying

I am calling invalidate() which is calling onDraw(). The bitmap that I wish to show on the screen is not being displayed after running doInBackGround(). Can anyone help?
Here is what I have tested out so far.
When I place the same line of code
canvas.drawBitmap();
in onPreExecute() it works, but in onPostExecute() it does not display the expected results.
This is my code:
public class FloorAppActivity extends Activity {
private Context globalContext;
private Point displaySize;
private int displayWidth;
private int displayHeight;
private String floorID;
private String floorName;
private String floorGridNumStr;
private int floorGridNum;
private String floorNumStr;
private int positionX;
private int positionY;
private int XCoord;
private int YCoord;
private int ZCoord;
private float signalStr;
private Integer dBm;
private Bitmap floorPlan;
private Bitmap userMark;
private Bitmap redPin;
private FloorView floorView;
private Connection conn = null;
private Canvas canvas=null;
private int newScrollRectX=0;
private int newScrollRectY=0;
private Paint paint;
private boolean a = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
globalContext = this;
floorID = getIntent().getStringExtra("floorID");
floorName = getIntent().getStringExtra("floorName");
positionX = getIntent().getIntExtra("userPositionX",-1);
positionY = getIntent().getIntExtra("userPositionY",-1);
dBm = getIntent().getIntExtra("BestSignal", -1);
//Get the grid number
if(Integer.parseInt(floorName.substring(floorName.lastIndexOf("_")+1))<10)
floorGridNumStr = floorName.substring(8, 9);
else
floorGridNumStr = floorName.substring(8, 10);
floorGridNum = Integer.parseInt(floorGridNumStr);
floorNumStr = floorName.substring(5,7);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
displaySize = new Point();
try {
// GetSize is not available in older models of Android
display.getSize(displaySize);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
displaySize.x = display.getWidth();
displaySize.y = display.getHeight();
}
try {
InputStream source = getAssets().open(floorID);
floorPlan = BitmapFactory.decodeStream(source);
displayWidth = Math.min(displaySize.x, floorPlan.getWidth());
displayHeight = Math.min(displaySize.y, floorPlan.getHeight());
userMark = BitmapFactory.decodeResource(getResources(),R.drawable.star);
redPin = BitmapFactory.decodeResource(getResources(),R.drawable.redpin);
floorView = new FloorView(this);
setContentView(floorView);
}
catch (IOException e) {
MapServerAPI server = new MapServerAPI(globalContext,"Retrieving floor plan. Please wait...") {
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (bitmap == null)
Toast.makeText(globalContext, "Error in retrieving floor plan!", Toast.LENGTH_LONG).show();
else {
floorPlan = bitmap;
displayWidth = Math.min(displaySize.x, floorPlan.getWidth());
displayHeight = Math.min(displaySize.x, floorPlan.getHeight());
userMark = BitmapFactory.decodeResource(getResources(),R.drawable.star);
redPin = BitmapFactory.decodeResource(getResources(),R.drawable.redpin);
floorView = new FloorView(globalContext);
setContentView(floorView);
}
}
};
server.execute(floorID);
}
}
#Override
public void onResume() {
super.onResume();
registerReceiver(broadcastReceiver,new IntentFilter("FingerPrint_LOCATION_UPDATE"));
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
// listen for user location change
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String result = intent.getStringExtra("location");
Toast.makeText(context,result,Toast.LENGTH_LONG).show();
String floorId = intent.getStringExtra("floorID");
floorName = intent.getStringExtra("name");
dBm = intent.getIntExtra("BestSignal", -1);
int userLocationX = intent.getIntExtra("userPositionX",-1);
int userLocationY = intent.getIntExtra("userPositionY",-1);
//Get the grid number
if(Integer.parseInt(floorName.substring(floorName.lastIndexOf("_")+1))<10)
floorGridNumStr = floorName.substring(8, 9);
else
floorGridNumStr = floorName.substring(8, 10);
floorGridNum = Integer.parseInt(floorGridNumStr);
floorNumStr = floorName.substring(5,7);
if(!floorId.equals(floorID)){
positionX = userLocationX;
positionY = userLocationY;
InputStream source=null;
try {
source = getAssets().open(floorID);
} catch (IOException e) {
}
floorPlan = BitmapFactory.decodeStream(source);
floorView.postInvalidate();
}
}
};
private class FloorView extends View {
private Rect displayRect; //rect we display to
private Rect scrollRect; //rect we scroll over our bitmap with
private int scrollRectX = 0; //current left location of scroll rect
private int scrollRectY = 0; //current top location of scroll rect
private float scrollByX = 0; //x amount to scroll by
private float scrollByY = 0; //y amount to scroll by
private float startX = 0; //track x from one ACTION_MOVE to the next
private float startY = 0; //track y from one ACTION_MOVE to the next
public FloorView(Context context) {
super(context);
// Destination rect for our main canvas draw. It never changes.
displayRect = new Rect(0, 0, displayWidth, displayHeight);
// Scroll rect: this will be used to 'scroll around' over the
// bitmap in memory.
if (positionX + displayWidth / 2 > floorPlan.getWidth())
scrollRectX = floorPlan.getWidth() - displayWidth;
else
scrollRectX = positionX - displayWidth / 2;
if (scrollRectX < 0)
scrollRectX = 0;
if (positionY + displayHeight / 2 > floorPlan.getHeight())
scrollRectY = floorPlan.getHeight() - displayHeight;
else
scrollRectY = positionY - displayHeight / 2;
if (scrollRectY < 0)
scrollRectY = 0;
scrollRect = new Rect(scrollRectX, scrollRectY, displayWidth, displayHeight);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Remember our initial down event location.
startX = event.getRawX();
startY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
float x = event.getRawX();
float y = event.getRawY();
// Calculate move update. This will happen many times
// during the course of a single movement gesture.
scrollByX = x - startX; //move update x increment
scrollByY = y - startY; //move update y increment
startX = x; //reset initial values to latest
startY = y;
invalidate(); //force a redraw
break;
}
return true; //done with this event so consume it
}
#Override
protected void onDraw(Canvas canvas1) {
canvas=canvas1;
// Our move updates are calculated in ACTION_MOVE in the opposite direction
// from how we want to move the scroll rect. Think of this as dragging to
// the left being the same as sliding the scroll rect to the right.
newScrollRectX = scrollRectX - (int)scrollByX;
newScrollRectY = scrollRectY - (int)scrollByY;
// Don't scroll off the left or right edges of the bitmap.
if (newScrollRectX < 0)
newScrollRectX = 0;
else if (newScrollRectX > (floorPlan.getWidth() - displayWidth))
newScrollRectX = (floorPlan.getWidth() - displayWidth);
// Don't scroll off the top or bottom edges of the bitmap.
if (newScrollRectY < 0)
newScrollRectY = 0;
else if (newScrollRectY > (floorPlan.getHeight() - displayHeight))
newScrollRectY = (floorPlan.getHeight() - displayHeight);
// We have our updated scroll rect coordinates, set them and draw.
scrollRect.set(newScrollRectX, newScrollRectY,
newScrollRectX + displayWidth, newScrollRectY + displayHeight);
paint = new Paint();
canvas.drawBitmap(floorPlan, scrollRect, displayRect, paint);
// Update user position
if (positionX >= newScrollRectX && positionX - newScrollRectX <= displayWidth
&& positionY >= newScrollRectY && positionY - newScrollRectY <= displayHeight)
canvas.drawBitmap(userMark,positionX-newScrollRectX-userMark.getWidth()/2,positionY-newScrollRectY-userMark.getHeight()/2,paint);
class AsyncTaskToConnect extends AsyncTask <Void, Void, Void>{
#Override
protected Void doInBackground(Void... cmd) {
// connect to database and retrieve values
return null;
}
#Override
protected void onPostExecute(Void v)
{//PE
if (positionX >= newScrollRectX && positionX - newScrollRectX <= displayWidth
&& positionY >= newScrollRectY && positionY - newScrollRectY <= displayHeight)
{
canvas.drawBitmap(redPin,480-newScrollRectX-userMark.getWidth()/2,90-newScrollRectY-userMark.getHeight()/2,paint);
}
//return null;
// Reset current scroll coordinates to reflect the latest updates,
// so we can repeat this update process.
scrollRectX = newScrollRectX;
scrollRectY = newScrollRectY;
}//PE
}
AsyncTaskToConnect[] asyncTaskC = null;
asyncTaskC = new AsyncTaskToConnect[1];
asyncTaskC[0] = new AsyncTaskToConnect();
asyncTaskC[0].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// Cache our new dimensions; we'll need them for drawing.
displayWidth = Math.min(w, floorPlan.getWidth());
displayHeight = Math.min(h, floorPlan.getHeight());
// Destination rect for our main canvas draw.
displayRect = new Rect(0, 0, displayWidth, displayHeight);
// Scroll rect: this will be used to 'scroll around' over the
// bitmap in memory.
if (positionX + displayWidth / 2 > floorPlan.getWidth())
scrollRectX = floorPlan.getWidth() - displayWidth;
else
scrollRectX = positionX - displayWidth / 2;
if (scrollRectX < 0)
scrollRectX = 0;
if (positionY + displayHeight / 2 > floorPlan.getHeight())
scrollRectY = floorPlan.getHeight() - displayHeight;
else
scrollRectY = positionY - displayHeight / 2;
if (scrollRectY < 0)
scrollRectY = 0;
scrollRect = new Rect(scrollRectX, scrollRectY, displayWidth, displayHeight);
super.onSizeChanged(w, h, oldw, oldh);
}
}
}
P.S. This is my first time posting. Please pardon me if i make mistakes in my post. Thanks.
I think the problem is that you are storing the Canvas object passed into the onDraw method. The object may not be valid after the onDraw method has returned.
It looks like you are trying to prepare a Bitmap on a background thread and then draw it on screen when it has been prepared. The way you do it is - prepare the Bitmap and just call invalidate on the View in onPostExecute method. Then in the onDraw method, you can take that Bitmap object and draw it using canvas.drawBitmap

Resources