When does image.setImageResource() set the image resource inside a function? - java

Goal: To click on an image in an app and get it to fade out to make a different image appear.
My Method: To make the 1st image fade away after 2000ms and AFTER THAT change the image resource of the 1st image to the 2nd image to make the 2nd image appear
I have a correct solution which was provided by my instructor, so I dont want any correct solution for this. What i want to know is why is my solution not working, i.e why is setImageResource() setting the Image1 to Image 2 at the beginning despite calling it at the end
This is the fade function i have created which the image1 goes to when it is clicked
public void fade(View view){
ImageView image1 = findViewById(R.id.image1);
image1.animate().alpha(0f).setDuration(2000);
image1.setImageResource(R.drawable.cat2);
}
Actual Output: Image 1 changes to Image 2 as soon as I click it and then Image 2 fades away
Problem: Inspite of calling setImageResource() at the end of the code, it actually sets the image resource at the beginning

You are never telling image1.setImageResource(R.drawable.cat2); wait for 2000 millisecond and execute, So image2 appears as soon as you click it.
Solution:
Call image1.setImageResource(R.drawable.cat2); After 2000ms
new Handler().postDelayed(() -> {
image1.setImageResource(R.drawable.cat2);
}, 2000);
This may help.

The animation is asynchronous in your code - it doesn't block/wait, but starts the animation (or rather, queues the animation to be started) and then immediately executes the next line, which sets the image. If you want to update your image once the animation is complete, you can use withEndAction and supply a callback.
image1.animate()
.alpha(0f)
.setDuration(2000)
.withEndAction(new Runnable() {
#Override
public void run() {
image1.setImageResource(R.drawable.cat2);
}
})
.start();

I think this will be help to you:
Fade In Fade Out Android Animation in Java
so use in onClickListener like this:
image1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
image1.setVisibility(View.GONE);
//Animation...
image2.setVisibility(View.VISIBLE);
}
});

Related

Handle second click on card view

Okay, I'm just trying to handle the second click on a CardView.
For example, Now when I click on the CardView, It will change background color for the CardView. Also, it should change the image in the ImageView.
If I understand your question: you wanna ask how to prevent from multiple click/tap on a view, if yes then you can handle it by adding following method into your Utility class
public static void avoidMultipleTapping(View view) {
view.setEnabled(false);
final Handler handler = new Handler();
handler.postDelayed(() -> view.setEnabled(true), 1000);
}
if you want to say something else you can comment below over my answer.

How to take a screenshot of a GridLayout and then share it

I have bingo app where there is a GridLayout showing all the numbers done, left.
I want to take a screenshot of it and then share it.
I have tried many posibillities and tried to do many thing, but none of them worked
case R.id.share:
//the answer should be here
the name of the GridLayout is gridLayout
if you need any other code of explanation, please tell me
Considering that we want to take the screenshot when a button is clicked, the code will look like this:
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Bitmap bitmap = takeScreenshot();
saveBitmap(bitmap);
}
});
Calling getDrawingCache(); will return the bitmap representing the view or null if cache is disabled, that’s why setDrawingCacheEnabled(true); should be set to true prior invoking getDrawingCache().
public Bitmap takeScreenshot() {
View rootView = findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
This code is from this website
The website also contains the code to save the screenshot taken.
Also question is possible duplicate of how to take a screen shot on a button click can anyone provide a android code

How to load a activity only when all the imageViews are loaded using Picasso

I am trying to make a app where there are two activity..
First activity have all images loaded using Picasso in a RecyclerView,When clicked it will take to second activity, which will enlarge the clicked picture. Again there is a another RecyclerView which will show other random images to pick from...
I just want to know how to load the second activity only after every photos are loaded in the first activity,else the screen looks blank and ugly.
You can using Picasso loading callback
Picasso.with(YourActivity.this)
.load(imageUrl)
.into(imageView, new com.squareup.picasso.Callback() {
#Override
public void onSuccess() {
// can click to open second activity
}
#Override
public void onError() {
//do smth when there is picture loading error
}
});

Horizontal Scroll View working unexpectedly

I am trying to create a calculator. I am working in the latest Android Studio. Like in calculators, all new tokes(numbers, operators) should be shown in the right and if the field is larger than the display, it should scroll to the latest token. I have already browsed and found a way to do the same.
The code for the same is:
private void scrollRight() {
horizontalScrollView = (HorizontalScrollView) findViewById(R.id.horizontalScrollView);
ViewTreeObserver viewTreeObserver = horizontalScrollView.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
horizontalScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
horizontalScrollView.scrollTo(entry.getWidth(), 0);
}
});
}
scrollRight is called by a onClick event which checks if a token is entered and calls this.
Everything is working perfectly, i.e. on every new token the scroll bar is scrolling to the end. But if I try to scroll to the beginning manually, it no longer works. After this every time a new token is pressed, the scroll bar first moves to the end and then back to the beginning.
The only option that remains is to restart the program. I tried debugging the OnGlobalLayout function but the debugger loses all frames while stepping out from the function, so it is difficult to know what exactly is making the scroll bar go to the beginning.
GIF to show the problem:
Please Help!
Try
horizontalScrollView.post(new Runnable() {
#Override
public void run() {
horizontalScrollView.fullScroll(View.FOCUS_RIGHT);
}
});
And call findViewById only once in onCreate.

Android animation only shows the last ArrayList element

I have 5 TextView fields that are meant to display a String and change the text every 10 seconds.
In order to make the change I have an AsyncTask that grabs the next 5 messages (doInBackground) and passes them to onPostExecute to be displayed in the UI.
When I display the messages without an animation, everything works perfectly fine and the messages rotate every 10 seconds via a new AsyncTask every time.
Now, when I attempt to use a simple fade-in/out animation on the TextViews, I can see all of them fading out and then back in with a placeholder string however the actual text messages I want to display are only displayed in the last TextView.
The AsyncTask is an inner-class of my MainActivity.java.
I have implemented an AnimationListener in MainActivity.java and due to that the objects below in onPostExecute ((TextView) mNextTextView & (String) mNextMessageToDisplay) are also declared as global variables in the main class.
Here's AsyncTask's onPostExecute:
protected void onPostExecute(List<String> mFiveMessagesToDisplay) {
super.onPostExecute(mFiveMessagesToDisplay);
for (int mTextViewCounter = 0; mTextViewCounter < 5; mTextViewCounter++) {
// Prepare the next TextView and message to use
mNextTextViewToUse = mTextViewArrayList.get(mTextViewCounter);
mNextMessageToDisplay = mFiveMessagesToDisplay.get(mTextViewCounter);
// Post and animate the message changes in the TextView
mNextTextViewToUse.startAnimation(mFadeOutAnimation);
}
}
And my AnimationListener:
private AnimationListener mFadeOutAnimListener = new AnimationListener() {
public void onAnimationStart(Animation animation) {}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
mNextTextViewToUse.setVisibility(View.INVISIBLE);
mNextTextViewToUse.setText(mNextMessageToDisplay);
mNextTextViewToUse.setVisibility(View.VISIBLE);
mNextTextViewToUse.startAnimation(mFadeInAnimation);
}
}
As you can see, my setText() method is applied on the mNextTextViewToUse object with the contents of mNextMessageToDisplay, which are as mentioned before both global variables in the main class.
Both ArrayLists, the one containing the messages and the other containing the correct, I have iterated over both and printed the contents - everything is in its place.
Reminding again that if I use setText() with the same TextView and String objects under onPostExecute, everything works perfectly fine just without the animation.
Many thanks in advance!
Your issue is that the loops finishes by the time the animation ends, that's why you see only the last message.
Lets say that mNextTextViewToUse points to TextView1. You start a fade out animation for this TextView. By the time the animation ends, mNextTextViewToUse points to a different textView object (because the loop continue to run while the fade out animation is playing) so when onAnimationEnd is being called (by the fade out animation of TextView1) mNextTextView points to TextView5, and basically you are setting the text to this text view only.
There are several ways to solve this / implement what you need, personally I would probably create my own TextView class (extending TextView of course) and I'll add a public method called setTextAnimated (String newText). It will look something like:
public void setTextAnimated (String newText) {
mNextText = newText;
startAnimation(mFadeOutAnim);
}
where your onAnimationEnd callback will simple call setText(mNextText) and then will start fade-in animation.
Using this you will avoid another issue - that if you use the same animation object on different views - they will share the same timeline and interpolator. The result is that if View1 start a fade out animation that should take 200ms, and View 5 starts the same animation after 140ms, View5 will immediately "jump" to the same alpha value that View1 is.
I found the solution!
I ended up completely removing the FOR loop logic and using recursion which raises a Boolean flag once it has used all 5 available TextViews.
The method that gets the next TextView and String message and execute the animated setText():
public void updateTextView(List<String> mMessages) {
mNextTextViewToUse = mTextViewArrayList.get(mCurrentMessageIndex);
mNextMessageToDisplay = mMessages.get(mCurrentMessageIndex);
mNextTextViewToUse.startAnimation(mFadeOutAnimation);
if (mCurrentMessageIndex == 4) {
mStopMessageDisplayRepeat = true;
} else {
mCurrentMessageIndex++;
}
}
The Runnable that calls the method above, while the recursion stop Boolean is false:
public Runnable mUpdateTextViewRunnable = new Runnable() {
final static int POSTDELAY_INTERVAL = 600;
#Override
public void run() {
updateTextView(mFiveMessages);
if (! mStopMessageDisplayRepeat) {
mMessageDisplayRepeatHandler.postDelayed(mUpdateTextViewRunnable, POSTDELAY_INTERVAL);
}
}
};
Execute the Runnable:
public void startTextViewRunnableRepeat() {
mUpdateTextViewRunnable.run();
}
This is how my AsyncTask's onPostExecute() looks like:
#Override
protected void onPostExecute(List<String> mFiveMessagesToDisplay) {
super.onPostExecute(mFiveMessagesToDisplay);
mFiveMessages = mFiveMessagesToDisplay;
startTextViewRunnableRepeat();
}

Categories

Resources