Created
November 4, 2025 10:31
-
-
Save sunmeat/c66d5224ea05f57528d630c013d0b918 to your computer and use it in GitHub Desktop.
fluid motion design android example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| MainActivity.java: | |
| package site.sunmeat.animation; | |
| import android.content.Intent; | |
| import android.content.res.ColorStateList; | |
| import android.os.Bundle; | |
| import android.view.View; | |
| import android.view.animation.OvershootInterpolator; | |
| import android.widget.Button; | |
| import android.widget.Toast; | |
| import androidx.appcompat.app.AppCompatActivity; | |
| import androidx.core.app.ActivityOptionsCompat; | |
| public class MainActivity extends AppCompatActivity { | |
| private Button btnTransition; | |
| @Override | |
| protected void onCreate(Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| setContentView(R.layout.activity_main); | |
| btnTransition = findViewById(R.id.btn_transition); | |
| // анімація на клік: scale + зміна кольору з overshoot (fluid motion) | |
| btnTransition.setOnClickListener(v -> { | |
| // плавне розширення на 10% з overshoot | |
| ////////////////////////////////////////////////////////////////// !!! | |
| v.animate() | |
| .scaleX(1.1f) | |
| .scaleY(1.1f) | |
| .setDuration(200) | |
| .setInterpolator(new OvershootInterpolator(1.0f)) // overshoot для природності | |
| .withEndAction(() -> { | |
| // transition до DetailActivity (shared element) | |
| View sharedElement = btnTransition; | |
| ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( | |
| MainActivity.this, sharedElement, "transition_button"); | |
| var intent = new Intent(MainActivity.this, DetailActivity.class); | |
| startActivity(intent, options.toBundle()); | |
| Toast.makeText(this, "Перехід завершено плавно!", Toast.LENGTH_SHORT).show(); | |
| }) | |
| .start(); | |
| btnTransition.setBackgroundTintList(ColorStateList.valueOf(getColor(R.color.green_positive))); | |
| }); | |
| } | |
| } | |
| ================================================================================================================= | |
| activity_main.xml: | |
| <?xml version="1.0" encoding="utf-8"?> | |
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:background="#FAFAFA" | |
| android:gravity="center" | |
| android:orientation="vertical" | |
| android:padding="32dp"> | |
| <Button | |
| android:id="@+id/btn_transition" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:backgroundTint="#2196F3" | |
| android:padding="16dp" | |
| android:text="Дізнатися більше" | |
| android:textSize="18sp" /> | |
| </LinearLayout> | |
| ================================================================================================================= | |
| DetailActivity.java: | |
| package site.sunmeat.animation; | |
| import android.os.Bundle; | |
| import android.view.animation.LinearInterpolator; | |
| import android.widget.TextView; | |
| import androidx.appcompat.app.AppCompatActivity; | |
| public class DetailActivity extends AppCompatActivity { | |
| @Override | |
| protected void onCreate(Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| setContentView(R.layout.activity_detail); | |
| // fade-in для всього екрану (fluid entrance) | |
| overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); | |
| // додаткова анімація: легке пульсування тексту | |
| TextView textView = findViewById(R.id.detail_text); | |
| textView.animate() | |
| .alpha(0f) | |
| .setDuration(0) | |
| .alpha(1f) | |
| .setDuration(800) | |
| .setInterpolator(new LinearInterpolator()) // лінійне для плавності | |
| .start(); | |
| } | |
| } | |
| ================================================================================================================= | |
| activity_detail.xml: | |
| <?xml version="1.0" encoding="utf-8"?> | |
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:background="#FAFAFA" | |
| android:gravity="center" | |
| android:orientation="vertical" | |
| android:padding="32dp"> | |
| <Button | |
| android:id="@+id/btn_transition" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:backgroundTint="#4CAF50" | |
| android:padding="16dp" | |
| android:text="Деталі" | |
| android:textSize="18sp" | |
| android:transitionName="transition_button" /> | |
| <TextView | |
| android:id="@+id/detail_text" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="16dp" | |
| android:text="Мінімалістичний дизайн з fluid motion" | |
| android:textColor="#2196F3" | |
| android:textSize="16sp" /> | |
| </LinearLayout> | |
| ================================================================================================================= | |
| res / values / colors.xml: | |
| <?xml version="1.0" encoding="utf-8"?> | |
| <resources> | |
| <color name="black">#FF000000</color> | |
| <color name="white">#FFFFFFFF</color> | |
| <color name="pink">#E91E63</color> | |
| <color name="blue_trust">#2196F3</color> | |
| <color name="green_positive">#4CAF50</color> | |
| </resources> | |
| ================================================================================================================= | |
| build.gradle.kts: | |
| ... | |
| implementation("androidx.transition:transition:1.6.0") | |
| ================================================================================================================= | |
| AndroidManifest.xml: | |
| ... | |
| <application | |
| tools:replace="android:label" | |
| android:allowBackup="true" | |
| android:dataExtractionRules="@xml/data_extraction_rules" | |
| android:fullBackupContent="@xml/backup_rules" | |
| android:icon="@mipmap/cat" | |
| android:label="TEST" | |
| android:roundIcon="@mipmap/cat" | |
| android:supportsRtl="true" | |
| android:theme="@style/Theme.AppCompat.Light.DarkActionBar"> | |
| <activity | |
| android:name=".MainActivity" | |
| android:exported="true"> | |
| <intent-filter> | |
| <action android:name="android.intent.action.MAIN" /> | |
| <category android:name="android.intent.category.LAUNCHER" /> | |
| </intent-filter> | |
| </activity> | |
| <activity | |
| android:name=".DetailActivity" | |
| android:exported="true"> | |
| </activity> | |
| </application> | |
| ... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment