Uygulamanız kullanılırken ekranda yeni bilgiler ve eski bilgiler görünür kaldırılır. Ekranda gösterilenleri hemen değiştirebilirsiniz. ve kullanıcılar aniden görünen yeni içeriği kaçırabilir. Animasyonlar yavaş ve kullanıcının bakış açısını harekete geçirerek güncellemelerin daha barizdir.
Bir görünümü göstermek veya gizlemek için kullanabileceğiniz üç yaygın animasyon bulunur: geçiş animasyonları ve kart çevirme animasyonları.
Çapraz geçiş animasyonu oluşturma
Kaybolma olarak da bilinen çapraz geçiş animasyonu, kademeli olarak kararır
bir View
veya
Aynı anda ViewGroup
diğerinde de beliriyor. Bu animasyon, sürekli olarak
uygulamanızda içerik veya görünümleri değiştirin. Burada gösterilen çapraz geçiş animasyonu,
ViewPropertyAnimator
Bu özellik, Android 3.1 (API düzeyi 12) ve sonraki sürümlerde kullanılabilir.
İlerleme göstergesinden metin içeriğine geçişe bir örnek aşağıda verilmiştir:
Görünümleri oluşturma
Çapraz geçiş yapmak istediğiniz iki görünümü oluşturun. Aşağıdaki örnek, ilerleme göstergesi ve kaydırılabilir metin görünümü:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView style="?android:textAppearanceMedium"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum"
android:padding="16dp" />
</ScrollView>
<ProgressBar android:id="@+id/loading_spinner"
style="?android:progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
Çapraz geçiş animasyonunu ayarlama
Çapraz geçiş animasyonunu ayarlamak için aşağıdakileri yapın:
- Geçiş yapmak istediğiniz görünümler için üye değişkenleri oluşturun. İhtiyacınız olanlar daha sonra animasyon sırasında görünümlerde değişiklik yaparken bu referansları kullanabilirsiniz.
- Karartılan görünümün görünürlüğünü ayarla
GONE
. Bu, görüntülemeyi devre dışı bırakır ve bunu düzen hesaplamalarından çıkarır. Bu hesaplama, yukarı işleniyor config_shortAnimTime
öğesini önbelleğe alın sistem özelliğini lütfen unutmayın. Bu özellik, standart bir "short" (kısa) süresi belirlenebilir. Bu süre, açıkça anlaşılmayan animasyonlar veya animasyonları da kapsar.config_longAnimTime
veconfig_mediumAnimTime
mevcuttur.
Aşağıda, önceki kod snippet'indeki düzeni etkinlik içerik görünümü:
Kotlin
class CrossfadeActivity : Activity() { private lateinit var contentView: View private lateinit var loadingView: View private var shortAnimationDuration: Int = 0 ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_crossfade) contentView = findViewById(R.id.content) loadingView = findViewById(R.id.loading_spinner) // Initially hide the content view. contentView.visibility = View.GONE // Retrieve and cache the system's default "short" animation time. shortAnimationDuration = resources.getInteger(android.R.integer.config_shortAnimTime) } ... }
Java
public class CrossfadeActivity extends Activity { private View contentView; private View loadingView; private int shortAnimationDuration; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_crossfade); contentView = findViewById(R.id.content); loadingView = findViewById(R.id.loading_spinner); // Initially hide the content view. contentView.setVisibility(View.GONE); // Retrieve and cache the system's default "short" animation time. shortAnimationDuration = getResources().getInteger( android.R.integer.config_shortAnimTime); } ... }
Görünümleri çaprazla tanıştırın
Görünümler uygun şekilde ayarlandığında, aşağıdakileri yaparak bunların çapraz geçişini yapın:
- Azalan görünüm için alfa değerini 0 ve görünürlüğü 0 olarak ayarlayın
Başlangıcından
VISIBLE
hedefineGONE
ayarı. Bu, görünümü görünür ancak şeffaf hale getirir. - Azalan görünüm için alfa değerini 0'dan 1'e taşıyın. kaybolan bir görünümde, alfa değerini 1'den 0'a hareket ettirin.
- Kullanım
onAnimationEnd()
Animator.AnimatorListener
, kararan görünümün görünürlüğünüGONE
olarak ayarlayın. Her ne kadar alfa değeri 0 ise görünümün görünürlüğününGONE
olarak ayarlanması görünümü engeller devre dışı bırakır ve bunu düzen hesaplamalarından çıkarır. Bu hesaplama, devam ediyor.
Aşağıdaki yöntemde bunun nasıl yapılacağına dair bir örnek gösterilmektedir:
Kotlin
class CrossfadeActivity : Activity() { private lateinit var contentView: View private lateinit var loadingView: View private var shortAnimationDuration: Int = 0 ... private fun crossfade() { contentView.apply { // Set the content view to 0% opacity but visible, so that it is // visible but fully transparent during the animation. alpha = 0f visibility = View.VISIBLE // Animate the content view to 100% opacity and clear any animation // listener set on the view. animate() .alpha(1f) .setDuration(shortAnimationDuration.toLong()) .setListener(null) } // Animate the loading view to 0% opacity. After the animation ends, // set its visibility to GONE as an optimization step so it doesn't // participate in layout passes. loadingView.animate() .alpha(0f) .setDuration(shortAnimationDuration.toLong()) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { loadingView.visibility = View.GONE } }) } }
Java
public class CrossfadeActivity extends Activity { private View contentView; private View loadingView; private int shortAnimationDuration; ... private void crossfade() { // Set the content view to 0% opacity but visible, so that it is // visible but fully transparent during the animation. contentView.setAlpha(0f); contentView.setVisibility(View.VISIBLE); // Animate the content view to 100% opacity and clear any animation // listener set on the view. contentView.animate() .alpha(1f) .setDuration(shortAnimationDuration) .setListener(null); // Animate the loading view to 0% opacity. After the animation ends, // set its visibility to GONE as an optimization step so it doesn't // participate in layout passes. loadingView.animate() .alpha(0f) .setDuration(shortAnimationDuration) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { loadingView.setVisibility(View.GONE); } }); } }
Kart çevirme animasyonu oluşturma
Kart, emülasyon yapan bir animasyon göstererek içerik görünümleri arasında geçiş yapıyor
bir kartın arkasına atılıyor. Burada gösterilen kart çevirme animasyonu
FragmentTransaction
.
Kart çevirme işlemi aşağıdaki gibi görünür:
Animatör nesnelerini oluşturma
Kart çevirme animasyonunu oluşturmak için dört animatöre ihtiyacınız var. İki animatör kartın ön yüzünün dışarı ve sola hareket etmesi ve sağa ve sola hareket edebilir. Diğer iki animasyon kartı, kartın arka yüzüyle sağa ve sağa doğru animasyonu yaparken hareket eder.
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Before rotating, immediately set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />
<!-- Rotate. -->
<objectAnimator
android:valueFrom="-180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 1. See startOffset. -->
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 0. See startOffset. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Before rotating, immediately set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />
<!-- Rotate. -->
<objectAnimator
android:valueFrom="180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 1. See startOffset. -->
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="-180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 0. See startOffset. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
Görünümleri oluşturma
Kartın her bir tarafı, üzerinde çalışmak istediğiniz iki metin görünümü, iki resim veya çevrilmiş görünüm kombinasyonları gibi arasında yer alır. Daha sonra canlandıracağınız parçalarda iki düzeni kullanın. İlgili içeriği oluşturmak için kullanılan Aşağıdaki düzen, bir kartın tek tarafında metin oluşturur:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#a6c"
android:padding="16dp"
android:gravity="bottom">
<TextView android:id="@android:id/text1"
style="?android:textAppearanceLarge"
android:textStyle="bold"
android:textColor="#fff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/card_back_title" />
<TextView style="?android:textAppearanceSmall"
android:textAllCaps="true"
android:textColor="#80ffffff"
android:textStyle="bold"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/card_back_description" />
</LinearLayout>
Sonraki düzende ise kartın diğer tarafı oluşturulur. Bu tarafta bir
ImageView
:
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/image1"
android:scaleType="centerCrop"
android:contentDescription="@string/description_image_1" />
Parçaları oluşturma
Kartın önü ve arkası için parça sınıfları oluşturun. Parçanızda
sınıfları değiştirdikten sonra,
onCreateView()
yöntemidir. Daha sonra üst etkinlikte bu parçanın örneklerini oluşturabilirsiniz
istediğiniz yeri seçin.
Aşağıdaki örnekte, üst etkinliğin içindeki iç içe yerleştirilmiş parça sınıfları gösterilmektedir vardır:
Kotlin
class CardFlipActivity : FragmentActivity() { ... /** * A fragment representing the front of the card. */ class CardFrontFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = inflater.inflate(R.layout.fragment_card_front, container, false) } /** * A fragment representing the back of the card. */ class CardBackFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = inflater.inflate(R.layout.fragment_card_back, container, false) } }
Java
public class CardFlipActivity extends FragmentActivity { ... /** * A fragment representing the front of the card. */ public class CardFrontFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_card_front, container, false); } } /** * A fragment representing the back of the card. */ public class CardBackFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_card_back, container, false); } } }
Kart çevirme animasyonu
Parçaları bir üst etkinlik içinde görüntüleyin. Bunu yapmak için düzeni oluşturun
seçin. Aşağıdaki örnek,
Ekleyebileceğiniz FrameLayout
parçasına böler:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Etkinlik kodunda, içerik görünümünü oluşturduğunuz düzene ayarlayın. Etkinlik oluşturulduğunda varsayılan parçanın gösterilmesi iyi bir uygulamadır. İlgili içeriği oluşturmak için kullanılan aşağıdaki örnek etkinlikte, kartonpiyer için kartın ön yüzünün varsayılan:
Kotlin
class CardFlipActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_activity_card_flip) if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .add(R.id.container, CardFrontFragment()) .commit() } } ... }
Java
public class CardFlipActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_activity_card_flip); if (savedInstanceState == null) { getSupportFragmentManager() .beginTransaction() .add(R.id.container, new CardFrontFragment()) .commit(); } } ... }
Kartın ön tarafı göründükten sonra, uygun bir zamanda çevirin. Değişkenin diğer tarafını da göstermek için şunları yapan kart:
- Parça geçişleri için oluşturduğunuz özel animasyonları ayarlar.
- Görüntülenen parçayı yeni bir parçayla değiştirir ve bu etkinliğe animasyon ekler animasyonlarla senkronize edebilirsiniz.
- Önceden görüntülenen parçayı, parça arka yığınına ekler. Böylece, Kullanıcı Geri düğmesine dokunduğunda, kart tekrar başa döner.
Kotlin
class CardFlipActivity : FragmentActivity() { ... private fun flipCard() { if (showingBack) { supportFragmentManager.popBackStack() return } // Flip to the back. showingBack = true // Create and commit a new fragment transaction that adds the fragment // for the back of the card, uses custom animations, and is part of the // fragment manager's back stack. supportFragmentManager.beginTransaction() // Replace the default fragment animations with animator // resources representing rotations when switching to the back // of the card, as well as animator resources representing // rotations when flipping back to the front, such as when the // system Back button is tapped. .setCustomAnimations( R.animator.card_flip_right_in, R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out ) // Replace any fragments in the container view with a fragment // representing the next page, indicated by the just-incremented // currentPage variable. .replace(R.id.container, CardBackFragment()) // Add this transaction to the back stack, letting users press // the Back button to get to the front of the card. .addToBackStack(null) // Commit the transaction. .commit() } }
Java
public class CardFlipActivity extends FragmentActivity { ... private void flipCard() { if (showingBack) { getSupportFragmentManager().popBackStack(); return; } // Flip to the back. showingBack = true; // Create and commit a new fragment transaction that adds the fragment // for the back of the card, uses custom animations, and is part of the // fragment manager's back stack. getSupportFragmentManager() .beginTransaction() // Replace the default fragment animations with animator // resources representing rotations when switching to the back // of the card, as well as animator resources representing // rotations when flipping back to the front, such as when the // system Back button is pressed. .setCustomAnimations( R.animator.card_flip_right_in, R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out) // Replace any fragments in the container view with a fragment // representing the next page, indicated by the just-incremented // currentPage variable. .replace(R.id.container, new CardBackFragment()) // Add this transaction to the back stack, letting users press // Back to get to the front of the card. .addToBackStack(null) // Commit the transaction. .commit(); } }
Dairesel açma animasyonu oluşturun
Animasyonları ortaya çıkarma, bir grubu gösterdiğinizde veya gizlediğinizde kullanıcılara görsel devamlılık sağlar
oluşturuyoruz. İlgili içeriği oluşturmak için kullanılan
ViewAnimationUtils.createCircularReveal()
yöntemi, bir görünümü ortaya çıkarmak veya gizlemek için kırpma dairesini canlandırmanızı sağlar. Bu
animasyonu
ViewAnimationUtils
sınıf,
Şu anda Android 5.0 (API düzeyi 21) ve sonraki sürümlerde kullanılabilir.
Aşağıda, önceden görünmez olan bir görünümün nasıl açığa çıkarılacağını gösteren bir örnek verilmiştir:
Kotlin
// A previously invisible view. val myView: View = findViewById(R.id.my_view) // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. val cx = myView.width / 2 val cy = myView.height / 2 // Get the final radius for the clipping circle. val finalRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() // Create the animator for this view. The start radius is 0. val anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0f, finalRadius) // Make the view visible and start the animation. myView.visibility = View.VISIBLE anim.start() } else { // Set the view to invisible without a circular reveal animation below // Android 5.0. myView.visibility = View.INVISIBLE }
Java
// A previously invisible view. View myView = findViewById(R.id.my_view); // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. int cx = myView.getWidth() / 2; int cy = myView.getHeight() / 2; // Get the final radius for the clipping circle. float finalRadius = (float) Math.hypot(cx, cy); // Create the animator for this view. The start radius is 0. Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0f, finalRadius); // Make the view visible and start the animation. myView.setVisibility(View.VISIBLE); anim.start(); } else { // Set the view to invisible without a circular reveal animation below // Android 5.0. myView.setVisibility(View.INVISIBLE); }
ViewAnimationUtils.createCircularReveal()
animasyonu beş parametre alır.
İlk parametre, ekranda gizlemek veya göstermek istediğiniz görünümdür. İlgili içeriği oluşturmak için kullanılan
sonraki iki parametre, kırpma merkezi için X ve Y koordinatlarıdır
ekleyin. Genelde bu, görünümün merkezidir, ancak
animasyonun seçtiği yerden
başlaması için kullanıcının dokunduğu işaret eder. İlgili içeriği oluşturmak için kullanılan
dördüncü parametre kırpma dairesinin başlangıç yarıçapıdır.
Yukarıdaki örnekte, ilk yarıçap sıfır olarak ayarlıdır. Böylece, daire daire tarafından gizleniyor. Son parametre nihai yarıçaptır anlamına gelir. Bir görünümü gösterirken, nihai yarıçapı animasyon bitmeden önce görünümün tamamen açılabilmesini sağlar.
Önceden görülebilen bir görünümü gizlemek için aşağıdakileri yapın:
Kotlin
// A previously visible view. val myView: View = findViewById(R.id.my_view) // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. val cx = myView.width / 2 val cy = myView.height / 2 // Get the initial radius for the clipping circle. val initialRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() // Create the animation. The final radius is 0. val anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0f) // Make the view invisible when the animation is done. anim.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) myView.visibility = View.INVISIBLE } }) // Start the animation. anim.start() } else { // Set the view to visible without a circular reveal animation below // Android 5.0. myView.visibility = View.VISIBLE }
Java
// A previously visible view. final View myView = findViewById(R.id.my_view); // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. int cx = myView.getWidth() / 2; int cy = myView.getHeight() / 2; // Get the initial radius for the clipping circle. float initialRadius = (float) Math.hypot(cx, cy); // Create the animation. The final radius is 0. Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0f); // Make the view invisible when the animation is done. anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); myView.setVisibility(View.INVISIBLE); } }); // Start the animation. anim.start(); } else { // Set the view to visible without a circular reveal animation below Android // 5.0. myView.setVisibility(View.VISIBLE); }
Bu örnekte, kırpma dairesinin ilk yarıçapı şu kadar büyük olur:
animasyon başlamadan önce görünmesi için görünümün herhangi bir Son
yarıçap, animasyon tamamlandığında görünümün gizlenmesi için sıfır olarak ayarlanır.
Görünümün görünürlüğünün şu şekilde ayarlanabilmesi için animasyona bir işleyici ekleyin:
Animasyon karesinde INVISIBLE
gerekir.
Ek kaynaklar
- Jetpack Compose ile Animasyon.
- Jetpack Compose ile hareketler.