Dari Dribbble ke Android Motion



Di Internet, ada banyak template animasi yang menarik dengan antarmuka pengguna yang indah dari aplikasi seluler, tetapi tidak ada banyak contoh dengan penerapan antarmuka ini. Terlepas dari banyaknya beragam kerangka kerja dan alat bawaan di Android SDK, seringkali tidak mudah bagi pengembang pemula untuk mengimplementasikan antarmuka pengguna yang indah, termasuk dengan templat yang sudah jadi.

Pada artikel ini, kami akan mencoba mengimplementasikan antarmuka pengguna yang dikembangkan oleh desainer Ivan Parfyonov untuk studio PLATES.


Pertama, buat dua fragmen: RecyclerFragment dan DetailsFragment .


Kerangka kerja Android Transition?


Kerangka kerja Android Transition bekerja dengan baik, tetapi ada beberapa nuansa. Pertama, kami ingin semuanya berfungsi untuk kami setidaknya di API 19, dan kedua, kami perlu menghidupkan beberapa elemen pengguna pada saat yang sama dan beberapa dari mereka hadir hanya dalam satu fragmen. Oleh karena itu, kami menerapkan animasi elemen transisi (transisi elemen bersama) secara manual menggunakan ViewPropertyAnimator .

Semua beres


  1. Kami menghitung koordinat akhir dari elemen yang dipilih dari daftar (koordinatnya di DerailsFragment ), daftarnya adalah RecyclerView ;
  2. Kami menyimpan koordinat saat ini (koordinat dalam RecyclerFragment ) dan meneruskannya ke DetailsFragment (ini diperlukan untuk animasi terbalik dengan API <21);
  3. Buat salinan item yang dipilih dari daftar;
  4. Kami membuat elemen yang dipilih tidak terlihat (bukan salinan, tetapi elemen itu sendiri);
  5. Tambahkan salinan yang dibuat pada langkah 3 ke tata letak root dari fragmen induk, dalam kasus kami ini adalah RecyclerFragment ;
  6. Kami memulai animasi elemen antarmuka yang tersisa dan memindahkan salinan yang dibuat ke koordinat akhir dari langkah 1;
  7. Ketika animasi selesai, buat transaksi dan tampilkan DetailsFragment ;
  8. Kami memulai animasi elemen antarmuka di DetailsFragment .

Animasi Elemen UI


Untuk menghidupkan Toolbar kami akan membuat View tambahan di RecyclerFragment dan menempatkannya di belakang layar di bagian atas. View ini akan dianimasikan dalam wadah Toolbar di DetailsFragment (warna biru pada gif) menggunakan ViewPropertyAnimator .

 <View android:id="@+id/details_toolbar_helper" android:layout_width="wrap_content" android:layout_height="@dimen/details_toolbar_container_height" android:background="@color/colorPrimary" app:layout_constraintTop_toTopOf="parent"/> // In RecyclerFragment details_toolbar_helper.translationY = -details_toolbar_helper.height 

gambar

BottomNavigationView dan RecyclerView juga diimplementasikan menggunakan ViewPropertyAnimator , tidak ada yang rumit (mengubah transparansi dan memindahkan).

Sedikit dari kerangka Transisi


Dengan kata-kata sederhana, maka kerangka transisi android, ketika mulai menggerakkan elemen transisi, membuat salinan konten elemen transisi ini (seperti layar cetak), membuat ImageView dari salinan ini, kemudian menambahkan gambar ini ke lapisan overlay tambahan di lapisan overlay fragmen yang disebut dan memulai animasi.

Kerangka transisi android tidak cukup cocok untuk kita, karena ketika animasi elemen transisi dimulai, maka semua elemen antarmuka pengguna lain dalam fragmen dihancurkan dan kami tidak dapat menghidupkannya. Yaitu Ketika kita mengklik item daftar di RecyclerFragment untuk membuka DetailsFragment dan memulai animasi transisi, maka semua elemen antarmuka lainnya di RecyclerFragment dihancurkan tanpa animasi.

Untuk mendapatkan hasil yang diinginkan, kami akan secara manual membuat salinan elemen yang dipilih dari daftar, menambahkannya ke lapisan overlay dan kemudian menghidupkan. Tapi di sini muncul masalah kecil, dokumentasi untuk metode ViewGroupOverlay add(view: View) mengatakan:
Jika tampilan memiliki orang tua, tampilan akan dihapus dari orang tua itu sebelum ditambahkan ke overlay.

Tetapi untuk RecyclerView ini tidak berfungsi, item yang dipilih tidak dihapus dari RecyclerView setelah ditambahkan ke lapisan overlay.

Inilah yang terjadi ketika kami menambahkan item yang dipilih ke lapisan overlay:



Dan kami membutuhkan ini:



Oleh karena itu, kami tidak akan menggunakan lapisan overlay, dan kami akan segera menambahkan salinannya ke tata letak root. Buat salinan konten dari item yang dipilih, tambahkan ke ImageView dan atur koordinat:

 fun View.copyViewImage(): View { val copy = ImageView(context) val bitmap = drawToBitmap() copy.setImageBitmap(bitmap) //  pre-Lollipop   ,   card view  ,      card view return (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { CardView(context).apply { cardElevation = resources.getDimension(R.dimen.card_elevation) radius = resources.getDimension(R.dimen.card_corner_radius) addView(copy) } } else { copy }).apply { layoutParams = this@copyViewImage.layoutParams layoutParams.height = this@copyViewImage.height layoutParams.width = this@copyViewImage.width x = this@copyViewImage.x y = this@copyViewImage.y } } 


Mengapa membuat salinan jika Anda hanya bisa menghidupkan barang yang dipilih langsung dari daftar?

Karena RecyclerView sendiri juga akan dianimasikan dan, karenanya, semua elemennya, termasuk yang dipilih, yang ingin kami animasikan secara terpisah.

Setelah itu, tambahkan salinan ke markup root dan mulai animasinya.

 override fun onClick(view: View) { val fragmentTransaction = initFragmentTransaction(view) val copy = view.createCopyView() root.addView(copy) view.visibility = View.INVISIBLE startAnimation(copy, fragmentTransaction) } 


Dan inilah yang kami dapatkan:



Garis finish


Animasi gif di atas terjadi di RecyclerFragment , dan setelah selesai kita perlu menampilkan DetailsFragment .

 .withEndAction { fragmentTransaction?.commitAllowingStateLoss() } 

Mengapa kami menggunakan commitAllowingStateLoss ?

Jika Anda tidak menggunakannya dan pada saat animasi akan ada, misalnya, perubahan orientasi layar, maka kita akan mendapatkan IllegalStateExeption . Ini ditulis dengan baik tentang itu.

Selanjutnya, kita mulai animasi elemen antarmuka pengguna yang diperlukan di DetailsFragment .

Jalankan semuanya bersama-sama




Tidak persis sama dengan aslinya, tetapi tampilannya mirip.

Contohnya


Kode sumber tersedia di GitHub , dan artikel ini juga tersedia dalam bahasa Inggris .

Terima kasih atas perhatian anda!

Source: https://habr.com/ru/post/id423235/


All Articles