Transition with new Material Design Support lib - android

I've tried to make an animation from a Floating Action Button to a new activity like said in this page :
http://android-developers.blogspot.be/2014/10/implementing-material-design-in-your.html
In section: Activity + Fragment Transitions
But I don't see any transition on screen.
What is the problem???
In Original Activity:
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:src="#drawable/ic_add_white_48dp"
app:backgroundTint="#color/spg_rosa"
android:transitionName="#string/transition_add_pdv"
app:borderWidth="0dp"
app:elevation="8dp"
app:fabSize="normal" />
In destination Activity, in mainLayout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/spg_azul"
android:gravity="center_horizontal"
android:transitionName="#string/transition_add_pdv"
android:orientation="vertical">
And the code:
fab = (FloatingActionButton) v.findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// I added parameters to Intent() because it was giving me error
Intent intent = new Intent(getActivity(), AddActivity.class);
String transitionName = getString(R.string.transition_add_pdv);
ActivityOptionsCompat options =
ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(),
fab, // The view which starts the transition
transitionName // The transitionName of the view we’re transitioning to
);
ActivityCompat.startActivity(getActivity(), intent, options.toBundle());
}
});
Any Idea?

To be able to use (Activity activity, View sharedElement, String sharedElementName) you must enable the content transitions feature.
This requires FEATURE_CONTENT_TRANSITIONS to be enabled on the calling
Activity to cause an exit transition. The same must be in the called
Activity to get an entering transition.
To do this, set the feature before the setContentView(int) in the onCreate of both the exiting and entering Activities:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
setContentView(R.layout.activity_main);
...
}
Note: This feature is for API 21+. Although, there are some work arounds libraries I believe e.g. github.com/andkulikov/transitions-everywhere

Related

Flickering(Blinking) screen when using Shared elements animation to change between activities

I'm developing an android app and using a shared element transition between the splash screen activity and my login activity. while the transition is happening i get to see the background of my phone, apps and everthing, the only thing that i can see from my application is the logo animation, everything else, gone.
Here is my code:
Splash Screen (Origin)
<LinearLayout
android:id="#+id/meofat_logo"
android:layout_width="86dp"
android:layout_height="86dp"
android:layout_gravity="center"
android:background="#drawable/meofat_logo"
android:orientation="vertical"
android:layout_marginTop="210dp"
android:elevation="24dp"
android:transitionName="logo"/>
<LinearLayout
android:id="#+id/meofat_tipo"
android:layout_width="160dp"
android:layout_height="50dp"
android:background="#drawable/meofat_tipo"
android:layout_gravity="center"
android:elevation="24dp"
android:transitionName="tipo"/>
Login Screen (Destination)
<LinearLayout
android:id="#+id/meofat_logo"
android:layout_width="58dp"
android:layout_height="58dp"
android:layout_gravity="center"
android:background="#drawable/meofat_logo"
android:orientation="vertical"
android:layout_marginTop="80dp"
android:elevation="24dp"
android:transitionName="logo"/>
<LinearLayout
android:id="#+id/meofat_tipo"
android:layout_width="106dp"
android:layout_height="33dp"
android:background="#drawable/meofat_tipo"
android:layout_gravity="center"
android:elevation="24dp"
android:transitionName="tipo"/>
SplashScreen Code:
public class RedirectActivity extends Activity {
private static int SPLASH_TIME_OUT = 2000;
LinearLayout logo,tipo;
Animation upToDown;
Animation downToUp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_redirect);
logo = (LinearLayout) findViewById(R.id.meofat_logo);
tipo = (LinearLayout) findViewById(R.id.meofat_tipo);
upToDown = AnimationUtils.loadAnimation(this,R.anim.uptodown);
logo.setAnimation(upToDown);
downToUp = AnimationUtils.loadAnimation(this,R.anim.downtoup);
tipo.setAnimation(downToUp);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
MEOFatSession session = new MEOFatSession(RedirectActivity.this);
if (session.isLoggedIn()){
Intent goToMeasurement = new Intent(RedirectActivity.this,
MeasurementActivity.class);
RetrofitInitializer.getInstance().addCredentials(session.getCredentials());
startActivity(goToMeasurement);
finish();
} else {
Intent goToLogin = new Intent(RedirectActivity.this,
LoginActivity.class);
ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.
makeSceneTransitionAnimation(RedirectActivity.this,findViewById(R.id.meofat_logo),
"logo");
startActivity(goToLogin, optionsCompat.toBundle());
finish();
}
}
},SPLASH_TIME_OUT);
}
}
A gif trying to illustrate the problem.
https://giphy.com/gifs/d1G6hKgTAsX5hOo0
Removing the finish() method solved the issue. Apparently it would destroy the activity during the animation causing it to vanish.
Like #GaboSampaio said, finish() caused the flickering. You can delay it :
Handler handler = new Handler();
handler.postDelayed(this::finish, 1000);
Intent goToLogin = new Intent(RedirectActivity.this, LoginActivity.class);
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
RedirectActivity.this,
// Now we provide a list of Pair items which contain the view we can transitioning
// from, and the name of the view it is transitioning to, in the launched activity
new Pair<View, String>(findViewById(R.id.logo_splash),
"tipo"));
ActivityCompat.startActivity(RedirectActivity.this, intent, activityOptions.toBundle());

onclicklistener on a viewgroup with its child views

I have a relative layout that I want to make tappable, including its child views.
<RelativeLayout
android:id="#+id/houses_rel_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="#drawable/white_grey_border_bottom">
<HorizontalScrollView
android:id="#+id/houses_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
...
</LinearLayout>
</HorizontalScrollView>
<TextView... />
.....
</RelativeLayout>
I want to set an onclicklistener on the relative layout, the horizontal view, and the textviews, and a separate onclicklistener on the icon.
#BindView(R.id.houses_rel_1)
ViewGroup mHouse;
#BindView(R.id.fav_icn_1)
ImageView mFavIcn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_house_list);
ButterKnife.bind(this);
mHouse.setOnClickListener(new ViewGroup.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(mContext, SomeActivity.class);
mContext.startActivity(intent);
}
});
mFavIcn.setOnClickListener(new View.OnClickListener() {
...
});
}
Currently, the new activity is staring only when I tap on the textviews, but nothing happens when I tap on the horizontalscrollview. Do I have to duplicate the onclicklistener to horizontalscrollview?
Please use setOnTouchListener() on horizontalScrollView instead of setOnClickListener().
Mmmmmm...The reason is very complicated. After I read the source code of HorizontalScrollView.java, I found it overrides these methods of View or ViewGroup--onTouchEvent, onInterceptTouchEvent.Without use super.onTouchEvent,super.onInterceptTouchEvent.It partly means if you set a OnClickListener on it(HorizontalScrollView), the onClick event will never be invoked.
If you want to know more about, you can read the source code too. It will more helpful then I telling you the reason, cuz I may have some misinterpretations in reading.
I hope that helps you.
Try grouped onClick of Butter Knife :
#OnClick({ R.id.houses_1, R.id.houses_rel_1 })
public void startSomeActivity() {
Intent intent = new Intent(mContext, SomeActivity.class);
mContext.startActivity(intent);
}

My ImageView doesn´t appear on my Device screen

I created a Layout and a Activity to that Layout.
In the Layout I only have an ImageView with a png image that is located in the Resources/Drawables.
When I launch the Application in my Device the ImageView doesn´t appear on the screen.
This is my XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="25px"
android:minHeight="25px"
android:gravity="center"
android:visibility="visible"
tools:visibility="visible">
<ImageView
android:layout_width="350.0dp"
android:layout_height="279.5dp"
android:id="#+id/OpeningLogo"
android:layout_gravity="center"
android:visibility="visible"
tools:visibility="visible"
android:src="#drawable/logo"
android:adjustViewBounds="true" />
</LinearLayout>
This is the Activity Code:
namespace *********
{
[Activity(Label = "xxxxxxxxx", MainLauncher = true, Icon = "#drawable/Logo")]
public class OpeningActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Opening);
Intent GoToLogin = new Intent(this, typeof(MainActivity));
Thread.Sleep(5000);
this.Finish();
StartActivity(GoToLogin);
}
}
}
If you want me to put something more tell me.
Thanks in advance!
Problem is that you are blocking the UI thread of that Activity and it is never actually shown as intended. The UI thread does not get time to actually draw anything on the screen.
Instead you should do something like:
namespace GridSocios
{
[Activity(Label = "xxxxxxxxx", MainLauncher = true, Icon = "#drawable/Logo", NoHistory = true)]
public class OpeningActivity : Activity
{
protected override async void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Opening);
await Task.Delay(5000);
var intent = new Intent(this, typeof(MainActivity));
StartActivity(intent);
}
}
}
Also notice the NoHistory = true flag is set. This means that you can't navigate back to this Activity after you have navigated away from it.

Android Studio Main Activity That has a button and gets the Fragment layout

Is it possible to have a button in the main activity and when the user clicks
it , the fragment layout will appear? Im new to Android Studio.If its possible
do you think you can show me an example of it.
It should be similar to the description provided here in the link just add the button to the activity instead of the fragment in this example
Button Click inside Fragment to open up new fragment
You can use it directly from the main activity like this example:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>
<Button
android:id="#+id/button"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="Click me"
/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.root_layout, new NewFragment());
transaction.commit();
//button.setVisibility(View.GONE);
}
});
}
}
Where NewFragment is just a black fragment.
The problem is the LinearLayout is replaced, but the button is not:
So you can set the visibility (as a commented in the code). But I suggest to create 2 fragments, one with the button and one with your content. Then in the activity onCreate() method, you can set the first fragment and replace it with the other one later.

Use of setVisibility(View.INVISIBLE) with pre Lollipop Circular Reveal library

I'm working on a project in which I want to use the Circular Reveal effect as per the Material Design. Project has minSDK = 11, so for compatibility with pre-Lollipop devices, I'm using this library https://github.com/ozodrukh/CircularReveal
I've a fragment with a FloatingActionButton that, when tapped, will transform itself in the CardView, like described here FAB transformations.
Once the card is revealed it has a button to revert the animation, re-transforming the card into the FAB. Now my problem is this: let's say that a user tap the FAB and the CardView is revealed. Now the user rotate his device, so the activity resets the fragment. What I want to achieve is the card stay visible and revealed, while the FAB should be disabled and invisible. The problem is that if I simply use setVisibility(View.INVISIBLE) on my FAB it doesn't work (note that if I use getVisibility() on it just after setting it invisible, it correctly returns me the value 4 == View.INVISIBLE, but the fab is still visible). I've to wrap the setVisibility(...) call inside a postDelayed() with at least 50-100 ms of delay to make the fab invisible.
So my question is: am I doing things right or there's a better way to accomplish what I want (because it seems very ugly to me)?
Here's some code. This is my XML layout of the fragment:
<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.support.design.widget.AppBarLayout
android:id="#+id/my_appbar"
android:layout_width="match_parent"
android:layout_height="#dimen/toolbar_expanded_height"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="70dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="#style/ToolbarPopupTheme"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
...
<io.codetail.widget.RevealFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/my_fragment" />
</io.codetail.widget.RevealFrameLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/fab_margin"
app:fabSize="mini"
app:layout_anchor="#+id/my_appbar"
app:layout_anchorGravity="bottom|left|start" />
</android.support.design.widget.CoordinatorLayout>
This is the XML layout of the included CardView:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_gravity="center"
card_view:cardCornerRadius="2dp"
android:visibility="invisible"
android:focusableInTouchMode="true">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent">
...
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end">
<Button android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Ok" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel" />
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
And this is the code of my Fragment:
public class MyFragment extends Fragment {
private static final String CARD_OPEN_TAG = "CARD_OPEN_TAG";
public static MyFragment newInstance(){
return new MyFragment();
}
private int cardOpen;
private FloatingActionButton fabAddPublication;
private CardView card;
private Button cardCancel;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_magazines, container, false);
toolbar = (Toolbar) rootView.findViewById(R.id.layout);
...
// Initialize view status
if (savedInstanceState != null){
cardOpen = savedInstanceState.getInt(CARD_OPEN_TAG);
} else {
cardOpen = -1;
}
...
// Get FAB reference
fab = (FloatingActionButton) rootView.findViewById(R.id.fab_id);
// Get card reference
card = (CardView) rootView.findViewById(R.id.card_id);
editorPublication.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Using this event because I need my card to be measured to move correctly fab at his center
if (cardOpen != -1){
// Move FAB to center of card
fab.setTranslationX(coordX); // WORKS
fab.setTranslationY(coordY); // WORKS
// fab.setVisibility(View.INVISIBLE) -> DOESN'T WORK, fab remain visible on top and at center of my card
// Ugly workaround
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Hide FAB
fab.setVisibility(View.INVISIBLE);
}
}, 50); // Sometimes fails: if device/emulator use too much time to "rotate" screen, fab stay visible
// Remove listener
ViewTreeObserver obs = card.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
obs.removeOnGlobalLayoutListener(this);
else obs.removeGlobalOnLayoutListener(this);
}
}
});
if (editorOpen != -1){
fab.setEnabled(false); // WORKS
card.setVisibility(View.VISIBLE); // WORKS
}
// Get editors buttons reference
cardCancel = (Button) card.findViewById(R.id.card_cancel_id);
// Set FAB listener
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Explode FAB
explodeFab(fab, card); // This method trigger the reveal animation
cardOpen = card.getId();
}
});
// Set editors button listeners
cardCancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Implode FAB
implodeFAB(fab, card); // This card reverts the reveal animation
cardOpen = -1;
}
});
...
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
...
outState.putInt(CARD_OPEN_TAG, cardOpen);
}
}
I don't think that what you're doing is correct and here's why:
1.
That circular reveal library you're using is incompatible with hardware acceleration on Android 11 to 17 (3.0 to 4.2). It's using Canvas.clipPath() - a method which was implemented in software only up to Android 4.3. It means that you have to turn hardware acceleration off or your app will crash on not supported OpenGL call.
The best way to clip layouts is to use Canvas.saveLayer()/restoreLayer(). It's the only way to support all devices, get antialiased image and support invalidate/layout/draw flow correctly.
2.
Relying on timers and layout listeners to change layouts means that something is not really working for you. Each change can be executed directly without waiting. You just have to find the right place for that piece of code.
Timers can also trigger when your app is in background. It means that it will crash while trying to access UI from Timer thread.
Maybe you're calling setVisibility(true) somewhere in the code and that's why your FAB is visible? Setting visibility is ok and should work without any delayed calls. Just save visibility as FAB's state and restore it after orientation change.
If you wish to position the FAB at the center of the toolbar, wrap them both in a FrameLayout (wrap_content) and position the FAB with layout_gravity="center". That should allow you to remove layout listener.
3.
support.CardView is broken and shouldn't be used at all. It looks and works a little bit different on Lollipop and on older systems. The shadow is different, the padding is different, content clipping doesn't work on pre-Lollipop devices, etc. That's why it's hard to get consistent, good results on all platforms.
You should consider using plain layouts for that purpose.
4.
Some animations are cool-looking, but hard to implement, doesn't give any value and quickly become irritating, because the user has to wait for the animation to finish each time he/she clicks the button.
I'm not saying no for your case, but you may consider removing the transformation and using a drop down menu, a bottom sheet, a static toolbar or a dialog for that purpose.

Categories

Resources