2
\$\begingroup\$

I am currently making an application where the user will launch the app and the first this we see is the app logo fade in at the center of the screen. After about a second, the logo will translate up and the rest of the content will appear. I currently have a lot of code and wanted to know if this is the most efficient way of doing what I am doing. It seems like a lot of code for 3 animations.

search_logo_animation.xml:

<?xml version="1.0" encoding="utf-8"?>
<set
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:fillAfter="true">
 <alpha
 android:duration="800"
 android:fromAlpha="0.0"
 android:interpolator="@android:anim/accelerate_interpolator"
 android:toAlpha="1.0" />
 <translate
 android:duration="800"
 android:fillAfter="true"
 android:fromYDelta="0%p"
 android:startOffset="2000"
 android:toYDelta="-30%p" />
</set>

search_container_animation.xml:

<?xml version="1.0" encoding="utf-8"?>
<set
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:fillAfter="true">
 <alpha
 android:duration="800"
 android:fromAlpha="0.0"
 android:interpolator="@android:anim/accelerate_interpolator"
 android:toAlpha="1.0" />
</set>

search_button_animation.xml:

<?xml version="1.0" encoding="utf-8"?>
<set
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:fillAfter="true">
 <alpha
 android:duration="800"
 android:fromAlpha="0.0"
 android:interpolator="@android:anim/accelerate_interpolator"
 android:toAlpha="1.0" />
</set>

search.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/search"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@color/colorPrimary"
 tools:context=".Search">
 <ImageView
 android:id="@+id/searchLogo"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerInParent="true"
 android:contentDescription="@string/app_logo"
 android:visibility="invisible"
 android:src="@mipmap/ic_logo" />
 <LinearLayout
 android:id="@+id/searchContainer"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_centerInParent="true"
 android:layout_marginLeft="@dimen/search_container_margin_left"
 android:layout_marginStart="@dimen/search_container_margin_left"
 android:layout_marginRight="@dimen/search_container_margin_right"
 android:layout_marginEnd="@dimen/search_container_margin_right"
 android:paddingLeft="@dimen/search_container_padding_left"
 android:paddingStart="@dimen/search_container_padding_left"
 android:paddingRight="@dimen/search_container_padding_right"
 android:paddingEnd="@dimen/search_container_padding_right"
 android:paddingTop="@dimen/search_container_padding_top"
 android:paddingBottom="@dimen/search_container_padding_bottom"
 android:orientation="vertical"
 android:visibility="invisible"
 android:background="@drawable/search_container">
 <LinearLayout
 android:id="@+id/searchMakeContainer"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical">
 <TextView
 android:id="@+id/searchMakeLabel"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="@string/make" />
 <TextView
 android:id="@+id/searchMakeSelection"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginLeft="@dimen/search_option_margin_left"
 android:layout_marginStart="@dimen/search_option_margin_left"
 android:textSize="@dimen/search_option_text_size"
 android:text="@string/any" />
 </LinearLayout>
 <LinearLayout
 android:id="@+id/searchModelContainer"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="@dimen/search_option_margin_top"
 android:orientation="vertical">
 <TextView
 android:id="@+id/searchModelLabel"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="@string/model" />
 <TextView
 android:id="@+id/searchModelSelection"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginLeft="@dimen/search_option_margin_left"
 android:layout_marginStart="@dimen/search_option_margin_left"
 android:textSize="@dimen/search_option_text_size"
 android:text="@string/any" />
 </LinearLayout>
 </LinearLayout>
 <Button
 android:id="@+id/searchButton"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_below="@id/searchContainer"
 android:layout_marginLeft="@dimen/search_button_margin_left"
 android:layout_marginStart="@dimen/search_button_margin_left"
 android:layout_marginRight="@dimen/search_button_margin_right"
 android:layout_marginEnd="@dimen/search_button_margin_right"
 android:layout_marginTop="@dimen/search_button_margin_top"
 android:text="@string/search_listings"
 android:textColor="@android:color/white"
 android:textAllCaps="false"
 android:visibility="invisible"
 android:background="@drawable/search_button_selector" />
</RelativeLayout>

Search.java:

public class Search extends AppCompatActivity implements AnimationListener {
 ImageView searchLogo;
 LinearLayout searchContainer;
 Button searchButton;
 Animation searchLogoAnimation, searchContainerAnimation, searchButtonAnimation;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.search);
 searchLogo = (ImageView) findViewById(R.id.searchLogo);
 searchContainer = (LinearLayout) findViewById(R.id.searchContainer);
 searchButton = (Button) findViewById(R.id.searchButton);
 searchLogoAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.search_logo_animation);
 searchLogoAnimation.setAnimationListener(this);
 searchContainerAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.search_container_animation);
 searchContainerAnimation.setAnimationListener(this);
 searchButtonAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.search_button_animation);
 searchButtonAnimation.setAnimationListener(this);
 searchLogo.startAnimation(searchLogoAnimation);
 }
 @Override
 public void onAnimationEnd(Animation animation) {
 if (animation == searchLogoAnimation) {
 searchContainer.startAnimation(searchContainerAnimation);
 searchButton.startAnimation(searchButtonAnimation);
 }
 }
 @Override
 public void onAnimationRepeat(Animation animation) {
 }
 @Override
 public void onAnimationStart(Animation animation) {
 }
}
asked Nov 13, 2016 at 22:53
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

First of all you could define styles for your layout search.xml files in your /res/values/styles.xml:

 <style name="LayoutStyleWide"> 
 <item name="android:layout_width">match_parent</item>
 <item name="android:layout_height">wrap_content</item>
 </style>
 <style name="TextViewSelectionStyle" parent="@style/LayoutStyleWide">
 <item name="android:layout_marginLeft="@dimen/search_option_margin_left"</item>
 <item name="android:layout_marginStart="@dimen/search_option_margin_left"</item>
 <item name="android:textSize="@dimen/search_option_text_size"</item>
 <item name="android:text="@string/any"</item>
 </style>

etc.

Combine anything that views have in common in styles.

Part of your layout search.xml file then could look like this:

 <LinearLayout
 android:id="@+id/searchMakeContainer"
 style="@style/LayoutStyleWide"
 android:orientation="vertical">
 <TextView
 android:id="@+id/searchMakeLabel"
 style="@style/LayoutStyleWide"
 android:text="@string/make" />
 <TextView
 android:id="@+id/searchMakeSelection"
 style="@style/TextViewSelectionStyle"/>
 </LinearLayout>
 <LinearLayout
 android:id="@+id/searchModelContainer"
 style="@style/LayoutStyleWide"
 android:layout_marginTop="@dimen/search_option_margin_top"
 android:orientation="vertical">
 <TextView
 android:id="@+id/searchModelLabel"
 style="@style/LayoutStyleWide"
 android:text="@string/model" />
 <TextView
 android:id="@+id/searchModelSelection"
 style="@style/TextViewSelectionStyle"
 android:textSize="@dimen/search_option_text_size"/>
 </LinearLayout>

About your Java code:

Personally I like to keep my onCreate method clean and readable, so I`d separate these lines into methods:

 private void initializeViews() {
 searchLogo = (ImageView) findViewById(R.id.searchLogo);
 searchContainer = (LinearLayout) findViewById(R.id.searchContainer);
 searchButton = (Button) findViewById(R.id.searchButton);
 accelerate = new AccelerateInterpolator();
 }

Then you can replace your XML animations with these methods, which are more dynamic:

 private void animateAlpha(View view, float toAlpha,
 int duration, Interpolator interpolator) {
 view.animate().alpha(toAlpha).setDuration(duration).setInterpolator(interpolator);
 }
 private void animateTranslation(View view, float translateToX, 
 float translateToY, int duration, Interpolator interpolator, int startDelay){
 view.animate()
 .translationY(translateToY)
 .translationX(translateToX)
 .setDuration(duration)
 .setInterpolator(interpolator)
 .setStartDelay(startDelay)
 .setListener(this);
 }

This way you can extend and reuse the animation methods easily, and you can get rid of all your animation XML files because you are using ViewPropertyAnimator.

Since you are only using AccelerateInterpolator you can define it as a field too.

Your search.java then could look like this:

public class Search extends AppCompatActivity implements AnimationListener {
 ImageView searchLogo;
 LinearLayout searchContainer;
 Button searchButton;
 Interpolator accelerate;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.search);
 initializeViews();
 animateAlpha(searchLogo, 1.0f, 800, accelerate);
 animateTranslation(searchLogo, 0, -30, 800, accelerate, 2000); // I'll leave it to you to get the -30% ;) 
 }
 @Override
 public void onAnimationEnd(Animation animation) {
 animateAlpha(searchContainer, 1.0f, 800, accelerate);
 animateAlpha(searchButton, 1.0f, 800, accelerate); 
 }
 @Override
 public void onAnimationRepeat(Animation animation) {
 }
 @Override
 public void onAnimationStart(Animation animation) {
 }
 private void initializeViews() {
 searchLogo = (ImageView) findViewById(R.id.searchLogo);
 searchContainer = (LinearLayout) findViewById(R.id.searchContainer);
 searchButton = (Button) findViewById(R.id.searchButton);
 accelerate = new AccelerateInterpolator();
 }
 private void animateAlpha(View view, float toAlpha,
 int duration, Interpolator interpolator) {
 view.animate().alpha(toAlpha).setDuration(duration).setInterpolator(interpolator);
 }
 private void animateTranslation(View view, float translateToX, 
 float translateToY, int duration, Interpolator interpolator, int startDelay){
 view.animate()
 .translationY(translateToY)
 .translationX(translateToX)
 .setDuration(duration)
 .setInterpolator(interpolator)
 .setStartDelay(startDelay)
 .setListener(this);
 }
}

But after all, it's just a matter of taste...

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
answered Nov 18, 2016 at 2:21
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.