I've seen other threads with this issue, but none of them has worked for me.
I have an Activity A, which calls Activity B. I'm doing a fade animation programmatically both entry and exit, and a shared FAB is translated to its new position. This translation works, but the fade does not.
Code of Activity A
profilePic.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// Activity A starting Activity B
Activity activity = MainScreenUI.this;
Intent intent = new Intent(MainScreenUI.this, ProfileUI.class);
int[] imageScreenLocation = new int[2];
profilePic.getLocationInWindow(imageScreenLocation);
intent.putExtra(Properties.PACKAGE + ".left", imageScreenLocation[0])
.putExtra(Properties.PACKAGE + ".top", imageScreenLocation[1])
.putExtra(Properties.PACKAGE + ".width", profilePic.getWidth())
.putExtra(Properties.PACKAGE + ".height", profilePic.getHeight());
startActivity(intent);
activity.overridePendingTransition(0, 0);
}
});
Code of Activity B
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
...
mTopLevelLayout = (CoordinatorLayout)findViewById(R.id.profile_coordinator);
mBackground = new ColorDrawable(Color.WHITE);
mTopLevelLayout.setBackground(mBackground);
if (savedInstanceState == null)
{
final ViewTreeObserver observer = mProfileFAB.getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
#Override
public boolean onPreDraw()
{
mProfileFAB.getViewTreeObserver().removeOnPreDrawListener(this);
...
_runEnterAnimation();
return true;
}
});
}
}
private void _runEnterAnimation()
{
mProfileFAB.setPivotX(0);
mProfileFAB.setPivotY(0);
mProfileFAB.setScaleX(mWidthScaleImage);
mProfileFAB.setScaleY(mHeightScaleImage);
mProfileFAB.setTranslationX(mLeftDeltaImage);
mProfileFAB.setTranslationY(mTopDeltaImage);
mProfileFAB.animate()
.setDuration(ANIM_DURATION)
.scaleX(1).scaleY(1)
.translationX(0).translationY(0)
.setInterpolator(ACCELERATE_DECELERATE_INTERPOLATOR);
// This animation is not applied
ObjectAnimator bgAnim = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255);
bgAnim.setDuration(ANIM_DURATION);
bgAnim.start();
}
#Override
public void onBackPressed()
{
_runExitAnimation(new Runnable() {
public void run() {
finish();
}
});
}
#Override
public void finish()
{
super.finish();
overridePendingTransition(0, 0);
}
private void _runExitAnimation(final Runnable endAction)
{
int[] currentLocation = new int[2];
mProfileFAB.getLocationOnScreen(currentLocation);
mTopDeltaImage = mThumbnailTop - currentLocation[1];
mProfileFAB.animate()
.setDuration(ANIM_DURATION)
.setStartDelay(0)
.scaleX(mWidthScaleImage).scaleY(mHeightScaleImage)
.translationX(mLeftDeltaImage).translationY(mTopDeltaImage)
.withEndAction(endAction);
// This animation is not working either
ObjectAnimator bgAnim = ObjectAnimator.ofInt(mBackground, "alpha", 0);
bgAnim.setDuration(ANIM_DURATION);
bgAnim.start();
}
XML of Activity B
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/profile_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Activities.ProfileUI"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.AppBarLayout
android:id="#+id/profile_appbar_layout"
android:layout_width="match_parent"
android:layout_height="192dp"
android:background="#drawable/filter_bottom_border">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/profile_collapsing_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:contentScrim="?attr/colorPrimary">
...
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#android:color/white"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
...
</android.support.v4.widget.NestedScrollView>
<com.wallakoala.wallakoala.Views.FloatingActionImageView
android:id="#+id/profile_floating_pic"
android:layout_width="84dp"
android:layout_height="84dp"
android:src="#drawable/female_icon"
app:borderWidth="0dp"
app:layout_anchor="#id/profile_appbar_layout"
app:layout_anchorGravity="bottom|center"/>
</android.support.design.widget.CoordinatorLayout>
The strange thing is that this logic is applied in other places and it's working fine, I don't know what I've messed here.
Thanks in advance,
Provide exit and enter animations inside overridePendingTransition() method in your activity A> onclick method. There you provided overridePendingTransition(0,0).
You should rather use overridePendingTransition() in the onCreate() method of the Activity that you are trying to open than after raising the intent for the same.
If you kept the parameters 0 just to hide your code in the question its fine, but if not, let me tell you that it expects animation resource files as the input parameters. You can probably use the fade animations available in the support library as:
overridePendingTransition(R.anim.abc_fade_in, R.anim.abc_fade_out);
It takes in the first parameter as the enter animation of the Activity being opened, the second parameter for the exit animation of the previous one.
Related
I want to implement the Extended FAB button in the format mentioned on the material website (https://kstatic.googleusercontent.com/files/8f9b57829c943c97be7c4b2485cf678f041dfe7c7ef523cfb2e97f1aeee21431f83d98cc07befeeed904fabb258298e3a7ac95f9da5d3da7a4adcff658cea851)
https://material.io/components/buttons-floating-action-button#types-of-transitions
Kindly help on how to achieve the same.
You can use the Material motion and the Transition between Views.
For example define in your layout:
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/root"
..>
<com.google.android.material.card.MaterialCardView
android:id="#+id/end_card"
android:visibility="gone" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
.. />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Then just define the MaterialContainerTransform:
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showEndView(fab);
}
});
with:
private void showEndView(View startView) {
// Construct a container transform transition between two views.
MaterialContainerTransform transition = new MaterialContainerTransform();
transition.setScrimColor(Color.TRANSPARENT);
transition.setInterpolator(new FastOutSlowInInterpolator());
//set the duration....
//Define the start and the end view
transition.setStartView(startView);
transition.setEndView(endCard);
transition.addTarget(startView);
// Trigger the container transform transition.
TransitionManager.beginDelayedTransition(root, transition);
if (startView != null) {
startView.setVisibility(View.INVISIBLE);
}
if (endCard != null) {
endCard.setVisibility(View.VISIBLE);
}
}
Note: it requires at least the version 1.3.0-alpha01.
What the title says. At first, I created a method to swap from one image to the other one, and it works. When I add the 2nd method though, to reverse the action and swap back to the first one, nothing changes. It does not even revert from the first image to the second one. Below is the code:
public void fade(View view) {
ImageView laxus = (ImageView) findViewById(R.id.laxus_shirt);
ImageView laxos2 = (ImageView) findViewById(R.id.laxus2);
laxus.animate().alpha(0f).setDuration(1000);
laxos2.animate().alpha(1f).setDuration(1000);
}
public void fadetoblack(View view) {
ImageView laxusius = (ImageView) findViewById(R.id.laxus_shirt);
ImageView laxosios2 = (ImageView) findViewById(R.id.laxus2);
laxosios2.animate().alpha(0f).setDuration(1000);
laxusius.animate().alpha(1f).setDuration(1000);
}
Thank you in advance.
You need to call start() to trigger the animation.
laxus.animate().alpha(0f).setDuration(1000).start();
laxos2.animate().alpha(1f).setDuration(1000).start();
I would suggest you to use Util method to perform crossfading. Something like below
public static void crossFade(View incomingView, View outGoingView, int outGoingViewVisibility) {
outGoingView.setAlpha(1);
ViewCompat.animate(outGoingView).alpha(0).setListener(new ViewPropertyAnimatorListener() {
#Override
public void onAnimationStart(View view) {
}
#Override
public void onAnimationEnd(View view) {
view.setVisibility(outGoingViewVisibility);
}
#Override
public void onAnimationCancel(View view) {
}
}).start();
incomingView.setVisibility(View.VISIBLE);
incomingView.setAlpha(0);
ViewCompat.animate(incomingView).setListener(null).alpha(1).start();
}
Maybe it will be an option to use ViewSwitcher.
Add a viewSwitcher with 2 ImageViews.
<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/switcher"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/laxus"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="#+id/laxus2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ViewSwitcher>`
On Activity onCreate add code
ViewSwitcher viewSwitcher=(ViewSwitcher)findViewById(R.id. switcher); // initiate a ViewSwitcher
Animation in = AnimationUtils.loadAnimation(this,android.R.anim.slide_in_left); // load in animation
Animation out = AnimationUtils.loadAnimation(this,android.R.anim.slide_out_right); // load out animation
viewSwitcher.setInAnimation(in); // set in Animation for ViewSwitcher
viewSwitcher.setOutAnimation(out); // set out Animation for ViewSwitcher
When you want to switch between ImageViews call method viewSwitcher.showNext(); or viewSwitcher.showPrevious();
To verify which view is displayed use viewSwitcher.getCurrentView();
I add a Snackbar to my app. The problem is that in API 19 it's not at the bottom of the screen.
In API 21 it's ok. Here is my layout
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data />
<android.support.design.widget.CoordinatorLayout
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:focusableInTouchMode="true">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/home_search_input_hint"
android:inputType="text"
android:maxLength="30"
android:maxLines="1"/>
</android.support.constraint.ConstraintLayout>
</android.support.design.widget.CoordinatorLayout>
</layout>
And my OnCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_home);
super.onCreate(savedInstanceState);
// binding
binding = DataBindingUtil.setContentView(this, R.layout.activity_home);
// snackbar test
Snackbar snackbar = Snackbar.make(binding.root, "Snackbar", Snackbar.LENGTH_INDEFINITE);
snackbar.show();
}
Do you have any ideas how to fix it?
UPDATE: It seems that margin from the bottom is really random, I rerun emulator and see this.
and this
If you use 26 or 27 support, it is probably this known bug: Google Issue Tracker: Snackbar wrong placement on the Android 4x versions
To workaround it, use a small time delay before showing the Snackbar. This is needed if you want to show the Snackbar immediately when the screen displays, in onCreateView() or onCreate().
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// For com.android.support:design:v26 or v27, use a small
// time delay, to prevent bottom gap bug on Android 4.4
if (isAdded()) { snackbar.show(); }
}
}, 500);
Because you have a time delay, remember to protect against null Activity by checking for isAdded() or check getActivity() != null.
This issue can be avoided by moving the code which shows snackbar to onGlobalLayout() like following.
binding.root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
// snackbar test
Snackbar snackbar = Snackbar.make(binding.root, "Snackbar", Snackbar.LENGTH_INDEFINITE);
snackbar.show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
binding.root.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
binding.root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
This is a bug which is still not fixed.
Workaround - small delay on pre-lollipop devices.
Delay not noticeable on UI.
Put these methods in your base fragment and base activity and use everywhere:
protected ViewGroup getRootView() {
return (ViewGroup) getView().getParent();
}
protected void showSnackbar(#StringRes int resId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
new Handler().postDelayed(() -> Snackbar.make(getRootView(), resId, Snackbar.LENGTH_SHORT).show(), 200);
} else {
Snackbar.make(getRootView(), resId, Snackbar.LENGTH_SHORT).show();
}
}
protected void showSnackbar(String message) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
new Handler().postDelayed(() -> Snackbar.make(getRootView(), message, Snackbar.LENGTH_SHORT).show(), 200);
} else {
Snackbar.make(getRootView(), message, Snackbar.LENGTH_SHORT).show();
}
}
I am a hybrid apps developer and new to android. I am trying to fix an android related issue for my hybrid app.
I have the following two methods on my activity: onStart and onPause.
When the app starts I need it to start as usual. When the app is on pause, I need to show an image (my companyLogo). If I set it with setContentView(R.layout.activity_base), the image is shown when the app starts again. Is there a way to dynamically create an image, and show it when app is on pause? Also, how do I remove the image once it starts? Since I am not hands on in Android, I am not sure how to go about it.
I suppose I need to create some sort of a Dialog and set an image view inside it.
Also, I am not sure, how to remove this image, when the app Starts again.
My code snippet:
public void onStart() {
Toast.makeText(getApplicationContext(), "App is in foreground", Toast.LENGTH_LONG).show();
}
public void onPause() {
Toast.makeText(getApplicationContext(), "App is in background", Toast.LENGTH_LONG).show();
setContentView(R.layout.activity_base);
}
This code is im run it. i think u need this.
inside ur activity
ImageView img_view;
TextView txt_show;
int images[] = {R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
img_view = (ImageView) findViewById(R.id.img_show);
txt_show = (TextView) findViewById(R.id.txt_my);
}
private void animate(final ImageView imageView, final int images[], final int imageIndex, final boolean forever) {
int fadeInDuration = 1000;
int timeBetween = 5000;
int fadeOutDuration = 1000;
imageView.setVisibility(View.INVISIBLE);
imageView.setImageResource(images[imageIndex]);
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(fadeInDuration);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setStartOffset(fadeInDuration + timeBetween);
fadeOut.setDuration(fadeOutDuration);
AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
animation.setRepeatCount(1);
imageView.setAnimation(animation);
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
if (images.length - 1 > imageIndex) {
animate(imageView, images, imageIndex + 1, forever);
} else {
if (forever) {
animate(imageView, images, 0, forever);
}
}
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
#Override
protected void onPause() {
super.onPause();
txt_show.setVisibility(View.GONE);
img_view.setVisibility(View.VISIBLE);
animate(img_view, images, 0, false);
}
#Override
protected void onResume() {
super.onResume();
img_view.setVisibility(View.GONE);
txt_show.setVisibility(View.VISIBLE);
}
inside ur xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/txt_my"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_gravity="center"
android:gravity="center"
android:text="buvan"
android:textColor="#color/colorPrimary" />
<ImageView
android:id="#+id/img_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
onResume is called of minimize from cme to screen.
try this one
#Override
protected void onResume() {
super.onResume();
setContentView(R.layout.activity_main);
}
The feature you want will not work without FLAG_SECURE, because when you send the app in the background, the view you are viewing, is an OS-handled view and only OS has the permission to update the view. For that reason, you have to call FLAG_SECURE to notify OS that this view needs to be secured. Otherwise, changing views would have worked.
I think you got the idea.
I'm doing some rudimentary exploration of Shared Element Transitions in Android L. The simple example I've setup has an image view translating from the top of the screen to the bottom of the screen during activity transitions and I've extended the transition duration so I can see things working. I've hit two problems so far trying to understand how Shared Element Transitions works.
1)When using only Enter/Return transitions (Exit/Reenter set to null). The enter transition is fine, but when the back button is pressed the view animates for a time, stops, then reappear in the final position. Seems similar to this question but I've set all the Exist/Reenter transitions to null so not sure why it happens.
2)When using only Exit/Reenter transitions (Enter/Return set to null). Nothing is happening, the view transitions down the screen like its following a default enter transition (300ms duration), and when back is pressed the view pops back to its original position.
How do I use Exit/Reenter transitions?
Here is my code:
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:src="#drawable/ic_launcher"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Animate!"
android:id="#+id/button"
android:layout_centerVertical="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
activity_second.xml
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView2"
android:src="#drawable/ic_launcher"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
getWindow().setAllowEnterTransitionOverlap(false);
getWindow().setAllowReturnTransitionOverlap(false);
getWindow().setSharedElementExitTransition(exitTransition());
getWindow().setSharedElementReenterTransition(reenterTransition());
//getWindow().setSharedElementExitTransition(null);
//getWindow().setSharedElementReenterTransition(null);
setContentView(R.layout.activity_main);
final View iView = findViewById(R.id.imageView);
iView.setTransitionName("image");
final Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
ActivityOptions options = ActivityOptions
.makeSceneTransitionAnimation(MainActivity.this, iView, "image");
startActivity(intent, options.toBundle());
}
});
}
private Transition exitTransition() {
ChangeBounds bounds = new ChangeBounds();
bounds.setInterpolator(new BounceInterpolator());
bounds.setDuration(2000);
return bounds;
}
private Transition reenterTransition() {
ChangeBounds bounds = new ChangeBounds();
bounds.setInterpolator(new OvershootInterpolator());
bounds.setDuration(2000);
return bounds;
}
}
SecondActivity.java
public class SecondActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
getWindow().setAllowEnterTransitionOverlap(false);
getWindow().setAllowReturnTransitionOverlap(false);
//getWindow().setSharedElementEnterTransition(enterTransition());
//getWindow().setSharedElementReturnTransition(returnTransition());
getWindow().setSharedElementEnterTransition(null);
getWindow().setSharedElementReturnTransition(null);
setContentView(R.layout.activity_second);
final View iView = findViewById(R.id.imageView2);
iView.setTransitionName("image");
}
#Override
public void onBackPressed() {
super.onBackPressed();
finishAfterTransition();
}
private Transition enterTransition() {
ChangeBounds bounds = new ChangeBounds();
bounds.setDuration(2000);
return bounds;
}
private Transition returnTransition() {
ChangeBounds bounds = new ChangeBounds();
bounds.setInterpolator(new DecelerateInterpolator());
bounds.setDuration(2000);
return bounds;
}
}
You shouldn't call finishAfterTransition() in onBackPressed(). The Activity super class will already do this for you.
You should call requestFeature() before super.onCreate(). Requesting Window.FEATURE_ACTIVITY_TRANSITIONS is not necessary if you are using the Theme.Material theme (or similar).
Calling setAllowEnterTransitionOverlap(false) and setAllowReturnTransitionOverlap(false) is redundant here. These determine the activity's window content transitions overlap... they don't affect the activity's shared element content transitions at all.
Setting exit and reenter shared element transitions is rarely necessary. You almost always want to use enter and return transitions instead. If you set only the exit and reenter shared element transitions and leave the enter and return shared element transitions null, the called activity will have no way of knowing how to animate the shared elements when the transition begins, and the animation will appear to be broken.
As I recall, there is a bug in L that causes the shared element return transition to be interrupted if it takes longer than the reenter transition duration. If you adjust your reenter transition duration (on the calling Activity), that should fix the interruption problem until the bug is fixed in MR1.
The exit and reenter transitions are for executing stuff before the shared element is allowed to transition. For example, if you want to lift your shared element before transferring it, that would be done in the shared element exit transition. The reenter would be used to do the opposite -- drop the view after it was transferred back. Most apps don't need it, but it is there for the rare one that does.