Skip to content

Commit 10fab10

Browse files
committed
Update
1 parent 37f4682 commit 10fab10

4 files changed

Lines changed: 78 additions & 1 deletion

File tree

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ dependencies {
5959
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2"
6060
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2"
6161
implementation 'androidx.appcompat:appcompat:1.7.1'
62-
implementation 'com.google.android.material:material:1.14.0-beta01'
62+
implementation 'com.google.android.material:material:1.14.0'
6363
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
6464
implementation "androidx.activity:activity-ktx:1.10.0"
6565
implementation 'androidx.core:core:1.18.0'

app/src/main/java/com/tool/tree/MainActivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.omarea.krscript.model.*
2727
import com.omarea.krscript.ui.ActionListFragment
2828
import com.omarea.krscript.ui.ParamsFileChooserRender
2929
import com.tool.tree.databinding.ActivityMainBinding
30+
import com.tool.tree.ui.FadeScalePageTransformer
3031
import com.tool.tree.ui.MainPagerAdapter
3132
import com.tool.tree.ui.SwipePager
3233
import com.tool.tree.ui.TabIconHelper
@@ -79,6 +80,7 @@ class MainActivity : AppCompatActivity() {
7980
if (!::adapter.isInitialized) {
8081
adapter = MainPagerAdapter(this)
8182
adapter.attach(binding.viewPager)
83+
binding.viewPager.setPageTransformer(FadeScalePageTransformer())
8284
}
8385
}
8486

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.tool.tree.ui
2+
3+
import android.view.View
4+
import kotlin.math.abs
5+
6+
/**
7+
* Hiệu ứng chuyển tab "Fade + Scale" kiểu Material: trang đang rời khỏi màn hình co nhỏ
8+
* dần + mờ dần, trang sắp hiện ra phóng to dần từ [minScale] lên 1 và hiện rõ dần.
9+
*
10+
* [minScale] - tỉ lệ thu nhỏ nhỏ nhất của trang khi nó lùi hẳn sang một bên (0..1).
11+
* [minAlpha] - độ mờ nhỏ nhất của trang khi nó lùi hẳn sang một bên (0..1).
12+
*/
13+
class FadeScalePageTransformer(
14+
private val minScale: Float = 0.90f,
15+
private val minAlpha: Float = 0.55f
16+
) : SwipePager.PageTransformer {
17+
18+
override fun transformPage(page: View, position: Float) {
19+
// Chặn trong [-1, 1]: ngoài khoảng này trang đã bị ViewGroup clip (không vẽ),
20+
// clamp lại để công thức không cho ra scale âm hoặc alpha âm trong trường hợp
21+
// fling/overshoot hiếm gặp.
22+
val clamped = position.coerceIn(-1f, 1f)
23+
val factor = 1f - abs(clamped)
24+
25+
val scale = minScale + (1f - minScale) * factor
26+
page.scaleX = scale
27+
page.scaleY = scale
28+
page.alpha = (minAlpha + (1f - minAlpha) * factor).coerceIn(0f, 1f)
29+
}
30+
}

app/src/main/java/com/tool/tree/ui/SwipePager.kt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,19 @@ class SwipePager @JvmOverloads constructor(
3535
fun onPageScrolled(position: Int, offset: Float) {}
3636
}
3737

38+
/**
39+
* Cho phép áp hiệu ứng chuyển trang tuỳ ý (fade, scale, depth...), tương tự
40+
* ViewPager.PageTransformer thế hệ 1. [position] là vị trí tương đối của trang so với
41+
* trang đang được chọn: 0 = đang hiển thị đầy đủ, -1 = lùi hẳn 1 trang bên trái,
42+
* 1 = lùi hẳn 1 trang bên phải.
43+
*/
44+
interface PageTransformer {
45+
fun transformPage(page: View, position: Float)
46+
}
47+
3848
private val pages = ArrayList<View>()
3949
private var listener: OnPageChangeListener? = null
50+
private var pageTransformer: PageTransformer? = null
4051

4152
var currentItem: Int = 0
4253
private set
@@ -71,10 +82,43 @@ class SwipePager @JvmOverloads constructor(
7182
listener = l
7283
}
7384

85+
fun setPageTransformer(transformer: PageTransformer?) {
86+
pageTransformer = transformer
87+
applyPageTransform()
88+
}
89+
90+
/**
91+
* Áp hiệu ứng transform lên từng trang dựa theo vị trí hiện tại của scrollX.
92+
* Gọi lại mỗi khi scrollX đổi (kéo tay, fling, settle) hoặc khi layout/thêm trang.
93+
*/
94+
private fun applyPageTransform() {
95+
if (width == 0) return
96+
val transformer = pageTransformer
97+
for (i in 0 until childCount) {
98+
val child = getChildAt(i)
99+
val position = (child.left - scrollX).toFloat() / width
100+
if (transformer != null) {
101+
transformer.transformPage(child, position)
102+
} else {
103+
// Không có transformer -> đảm bảo trang luôn ở trạng thái gốc
104+
child.alpha = 1f
105+
child.scaleX = 1f
106+
child.scaleY = 1f
107+
child.translationX = 0f
108+
}
109+
}
110+
}
111+
112+
override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
113+
super.onScrollChanged(l, t, oldl, oldt)
114+
applyPageTransform()
115+
}
116+
74117
fun addPage(view: View) {
75118
pages.add(view)
76119
addView(view)
77120
requestLayout()
121+
applyPageTransform()
78122
}
79123

80124
fun getPageCount(): Int = pages.size
@@ -131,6 +175,7 @@ class SwipePager @JvmOverloads constructor(
131175
pendingItem = null
132176
scrollTo(target * w, 0)
133177
}
178+
applyPageTransform()
134179
}
135180

136181
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {

0 commit comments

Comments
 (0)