In my app m trying to implement shared element transition between listview name from one activity and Toolbar title in the next activity. The problem i am facing is that shared element is not animated as it should be instead its animated along with the entire layout enter and exit transitions.
gif animation
here the insurance text should animate separately from the entire animation.
Calling Activity animations are as follows:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setSharedElementReturnTransition(TransitionInflater.from(this)
.inflateTransition(R.transition.trans_move));
// getWindow().setSharedElementExitTransition(new TransitionSet()
// .addTransition(new Fade()));
Slide slideTransition = new Slide();
slideTransition.setSlideEdge(Gravity.LEFT);
slideTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
getWindow().setReenterTransition(slideTransition);
getWindow().setExitTransition(slideTransition);
}
setShareElementExitTransition has no effect on the transition so commented it out
Intent used for starting the second activity
ActivityOptionsCompat activityOptions
= ActivityOptionsCompat.makeSceneTransitionAnimation(
HomeActivity.this,
new Pair<>(view.findViewById(R.id.nameTextView),
SharedCertificatesActivity.ab_title)
);
Intent _intent=new Intent(mContext, SharedCertificatesActivity.class);
ActivityCompat.startActivity(HomeActivity.this,
_intent, activityOptions.toBundle());
The Second activity has the following scenes transitions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Re-enter transition is executed when returning to this activity
Slide slideTransition = new Slide();
slideTransition.setSlideEdge(Gravity.LEFT);
slideTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
Slide slideRightTransition = new Slide();
slideRightTransition.setSlideEdge(Gravity.RIGHT);
slideRightTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
// getWindow().setAllowReturnTransitionOverlap(true);
getWindow().setReenterTransition(slideRightTransition);
getWindow().setExitTransition(slideTransition);
// getWindow().setSharedElementEnterTransition(TransitionInflater.from(this)
// .inflateTransition(R.transition.trans_move));
ViewCompat.setTransitionName(title, ab_title);
}
i also found a similar problem here on SO but the solution mentioned there didn't work for me.
if its above problem then the layout for the second activity is as below:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="#color/primary"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
android:fontFamily="sans-serif-medium"
android:text="Binder Name"
android:textColor="#color/_kAppearanceUINavigationBarTextColor"
android:textSize="20sp" />
</android.support.v7.widget.Toolbar>
<include layout="#layout/binder" />
</LinearLayout>
.
.
.
</android.support.design.widget.CoordinatorLayout>
Any help would be highly appreciated
Resolved the issue
The issue was mainly due the animation timings issue. Shared element was animating much faster (default value) as compared to the other window animations. Changed the setupWindowAnimations method in the second activity as follows
private void setupWindowAnimations() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Slide slideTransition = new Slide();
slideTransition.setSlideEdge(Gravity.LEFT);
slideTransition.setInterpolator(new DecelerateInterpolator());
slideTransition.setDuration(460);
Slide slideRightTransition = new Slide();
slideRightTransition.setSlideEdge(Gravity.RIGHT);
slideRightTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
getWindow().setReenterTransition(slideRightTransition);
getWindow().setExitTransition(slideTransition);
getWindow().setEnterTransition(slideTransition);
getWindow().setSharedElementEnterTransition(new ChangeBounds().setDuration(450));
getWindow().setSharedElementReturnTransition(null);
ViewCompat.setTransitionName(title, ab_title);
ViewCompat.setTransitionName(menu1, fab_anim);
}
}
Now is more smooth and the shared element transition as per the expected result. Credit goes to guides.codepath.com and George Mount blog for clearing out more about shared element transitions.
Note: There is google bug for returning back the shared element textview back to the calling activity which is till date not resolved. so had to disable the shared element return transition from the calling activity.
Related
I have an activity with a recyclerview in it which is populated with images. If an item on the recyclerview is pressed I need that image to grow to the full size of the screen and then change the toolbar and be in a new activity with its screen a full size image of the clicked item. I then also need a new toolbar.
Any ideas on how to go about this?
Check shared transitions, this might be what you want.
https://guides.codepath.com/android/Shared-Element-Activity-Transition
Try this one.
I think this will be helpful to you.
link
You can use Fragment Transition
public class DetailsTransition extends TransitionSet {
public DetailsTransition() {
setOrdering(ORDERING_TOGETHER);
addTransition(new ChangeBounds()).
addTransition(new ChangeTransform()).
addTransition(new ChangeImageTransform()));
}
}
https://medium.com/#bherbst/fragment-transitions-with-shared-elements-7c7d71d31cbb#.9t2bqq23m
https://www.raywenderlich.com/126528/android-recyclerview-tutorial
I got the solution of this.. Its quite simple btw :-)
Add the android:transitionName="ouranimation" attribute to the views that you want to animate..
for example :
In activity_main.xml :-
<android.support.v7.widget.CardView
...>
<ImageView
android:id="#+id/ivProfile"
android:transitionName="profile"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="160dp" />
...
</android.support.v7.widget.CardView>
In detail_activity.xml :-
<LinearLayout
...>
<ImageView
android:id="#+id/ivProfile"
android:transitionName="profile"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="380dp" />
...
</LinearLayout>
Now just start the target activity by specifying a bundle of those shared elements and views from the source. NOTE:- This transition only works on api level greater than 21 Lollipop.
Intent intent = new Intent(this, MyDetailsActivity.class);
// pass the data through intent if you need...
intent.putExtra("key", detail);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation((Activity) context, (View)ivProfile, "ouranimation");
startActivity(intent, options.toBundle());
To reverse this animation back to the MainActivity, just call this Activity.supportFinishAfterTransition() method instead of Activity.finish()....
I have a shared element transition when a `RecyclerView item click starts a detail Activity, but the ripple effect on the item click is never visible
Start Activity with shared element transition
Intent intent = IntentUtils.createDetailsIntent(InspectionListFragment.this.getContext(), record);
Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(),
view, getString(R.string.transition_element)).toBundle();
getActivity().startActivity(intent, options);
I noticed this log message
D/OpenGLRenderer: endAllStagingAnimators on 0x95e86600 (RippleDrawable) with handle 0xaa6c2760
If I remove the transition, the ripple works (and I don't see this message).
Delay Activity start using Handler
If I use a Handler with postDelayed to start the Activity, the results were mixed. I see the ripple, but the transition is not as smooth:
handler.postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = IntentUtils.createDetailsIntent(InspectionListFragment.this.getContext(), record);
Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(),
view, getString(R.string.transition_element)).toBundle();
getActivity().startActivity(intent, options);
}
}, 200);
Using ListView
Note that using a ListView with the same item layout and makeSceneTransitionAnimation works fine. Unfortunately this is not suitable.
The item layout
<LinearLayout
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
I ran into the same issue when I had an ImageView within the card as the shared element. I was able to resolve it by using the CardView as the source view for the shared element transition (and the ripple effect) instead.
<android.support.v7.widget.CardView
android:id="#+id/itemCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardCornerRadius="#dimen/card_corner_radius"
app:cardElevation="#dimen/card_elevation"
android:layout_gravity="center"
android:clickable="true"
android:onClick="#{onItemClick}"
android:foreground="?android:attr/selectableItemBackground"
>
I'm using data binding, but the shared element change was essentially just selecting a different source view:
// before:
//onItemClickListener.onItemClick(view, getAdapterPosition(), getItemId(), Pair.create((View)b.itemImage, "activity_image"));
// after:
onItemClickListener.onItemClick(view, getAdapterPosition(), getItemId(), Pair.create((View)b.itemCard, "activity_image"));
Before this, I also tried using postDelayed with a short delay, but I found that approach added too much delay to the navigation for my liking.
I'm trying to do a simple shared element transition where a row of the clicked list item transitions into the top header view of the resulting activity. I want the top header view to take the position of the list item, fade itself in, then transform to its final position.
This is the simple sharedElementEnterTransition that I wrote for the called activity:
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<fade android:fadingMode="fade_out" />
<changeBounds />
<changeTransform />
<changeImageTransform />
</transitionSet>
However, the fade transition isn't doing anything. I see the resulting view suddenly pop up on the spot then transforms to the final position.
Here's where I start the activity
view.setOnClickListener(view -> {
final Intent intent = new Intent(...);
view.setTransitionName("test");
final ActivityOptions options =
ActivityOptions.makeSceneTransitionAnimation(activity, view, "test");
startActivity(intent, options.toBundle());
});
Can't quite figure out what's happening. Anyone has any ideas? The layout codes are exactly what you would expect with with android:transitionName="test".
Meanwhile debugging Visibility class, I figured out that target view was not the expected one, therefore I forced it to test it, and it seems working. However, I don't know if this is the perfect solution, because I also agreed that it should work as other transitions (automatically)
sharedElementEnterTransition = Fade(Visibility.MODE_IN).addTarget(your_view)
If you want a sequential transitions, you might need to create a TransitionSet and add it
val fadeIn = Fade(Visibility.MODE_IN).addTarget(your_view)
val move = TransitionInflater.from(context)
.inflateTransition(android.R.transition.move)
val transitionSet = TransitionSet().apply {
ordering = ORDERING_TOGETHER
addTransition(move)
addTransition(fadeIn)
}
sharedElementEnterTransition = transitionSet
I'm trying to customize the "Navigate up" default contentDescription that is associated with the up button of the ActionBar (I'm using ActionBarSherlock).
From ActionBarView's source:
public void setHomeButtonEnabled(boolean enable) {
mHomeLayout.setEnabled(enable);
mHomeLayout.setFocusable(enable);
// Make sure the home button has an accurate content description for accessibility.
if (!enable) {
mHomeLayout.setContentDescription(null);
} else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
mHomeLayout.setContentDescription(mContext.getResources().getText(
R.string.abs__action_bar_up_description));
} else {
mHomeLayout.setContentDescription(mContext.getResources().getText(
R.string.abs__action_bar_home_description));
}
}
so the key would be how to get a reference to mHomeLayout. getWindow().getDecorView().findViewById(android.R.id.home) is not working, as it's returning an ImageView.
How could I do?
Thanks ;)
layout
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#color/colorPrimary"
android:elevation="4dp"
android:layout_height="wrap_content"
android:layout_width="match_parent"
app:layout_scrollFlags="scroll|enterAlways">
</android.support.v7.widget.Toolbar>
code
public Toolbar toolbar;
...
setContentView(layout);
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(layoutTitle);
setSupportActionBar(toolbar);
...
getSupportActionBar().setHomeActionContentDescription("Go Back To XYZ Screen");
In xml, use "navigationContentDescription"
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_alignParentTop="true"
app:navigationContentDescription="#string/back"/>
Here how I can do what you need in a previous project :
((View) getWindow().getDecorView().findViewById(android.R.id.home).getParent().getParent()).setContentDescription("blablabla");
Using viewHierarchy plugin helps me to understand how ActionBar layout is build.
In case someone needs to set the ActionBar's home-button's content-description for UIAutomator, use
((View) getWindow().getDecorView().findViewById(android.R.id.home).getParent()).setContentDescription("MANUALLYSET-home-up");
and access the view in your UIAutomatorTestCase using
new UiObject(new UiSelector().description("MANUALLYSET-home-up").className("android.widget.FrameLayout"));
For some reason the additional *.getParent() did not work, instead Android uses some auto-generated content-description value for that parent which may differ in some Android versions (e.g. "app_name, Close navigation drawer" on KITKAT and "app_name, Navigate up" on JELLYBEAN). Accessing its child works too, fortunately.
Kind regards
I've created a countdown timer that counts Days:Hrs:Mins:Sec. using regular text view and updating it using my handler works fine for me.
however I want to create a cool animation for the changing digits:
1st Q:
I have 2 options as I see it to draw the numbers:
1. using a home made font applied with a style
2. using a textview/btn with no text on them and applying a backrgound image using setBackgroundResource()
--what should I choose?
2nd Q:
I've created a wrapper for ViewFlipper(not extending it)
public class transitionair extends Activity {
SpecialFlipperWrapper m_thousand;
SpecialFlipperWrapper m_hundred;
SpecialFlipperWrapper m_tens;
SpecialFlipperWrapper m_ones;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
ViewFlipper flipper_Tsnds=(ViewFlipper)findViewById(R.id.yearThousand);
m_thousand = new SpecialFlipperWrapper(flipper_Tsnds, this, 9);
ViewFlipper flipper_Hndrds=(ViewFlipper)findViewById(R.id.yearHundread);
m_hundred = new SpecialFlipperWrapper(flipper_Hndrds, this, 9);
ViewFlipper flipper_Tns=(ViewFlipper)findViewById(R.id.yearTens);
m_tens = new SpecialFlipperWrapper(flipper_Tns, this, 9);
ViewFlipper flipper_Ons=(ViewFlipper)findViewById(R.id.yearOnes);
m_ones = new SpecialFlipperWrapper(flipper_Ons, this, 9);
m_thousand.startFlipping();
m_hundred.startFlipping();
m_tens.startFlipping();
m_ones.startFlipping();
}
}
however trying to fetch one of the latter views that come after the yearThousand id are retrieving null
XML I'm Using is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ViewFlipper
android:id="#+id/yearThousand"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ViewFlipper
android:id="#+id/yearHundread"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ViewFlipper
android:id="#+id/yearTens"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ViewFlipper
android:id="#+id/yearOnes"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
ps xml's for the animation itself are working so I left them out
Main questions is: can I make it better?
second question is: how?
third question is why is my layout returning null on the second call to it and how can I avoid it?
10XX