Skip to content

Commit e709415

Browse files
committed
transition sample finish
1 parent a66770b commit e709415

File tree

3 files changed

+114
-126
lines changed

3 files changed

+114
-126
lines changed

sample/src/main/java/me/brucezz/sample/DetailActivity.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import android.os.Bundle;
44
import android.support.annotation.Nullable;
5-
import android.support.v4.content.ContextCompat;
65
import android.support.v7.app.AppCompatActivity;
76
import android.view.View;
87
import android.widget.ImageView;
@@ -32,11 +31,9 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
3231
mContent = findViewById(R.id.detail_content);
3332

3433
Card card = getIntent().getParcelableExtra("card");
35-
int padding = getIntent().getIntExtra("padding", 0);
36-
mImageView.getLayoutParams().height -= padding;
37-
mImageView.setImageDrawable(ContextCompat.getDrawable(this, card.mImage));
34+
mImageView.setImageResource(card.mImage);
3835
StatusBarUtil.setColor(this, card.mBgColor);
39-
mTextView.setText(card.mTitle);
36+
mTextView.setText("哈哈哈 改变一下标题 ~" + card.mTitle);
4037

4138
animContent();
4239
}

sample/src/main/java/me/brucezz/sample/MainActivity.java

Lines changed: 83 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import android.animation.ValueAnimator;
66
import android.content.Intent;
77
import android.os.Bundle;
8-
import android.os.Handler;
9-
import android.os.Message;
108
import android.support.annotation.ColorInt;
119
import android.support.v7.app.AppCompatActivity;
1210
import android.support.v7.widget.CardView;
@@ -30,20 +28,7 @@ public class MainActivity extends AppCompatActivity {
3028
SimpleCardAdapter mCardAdapter;
3129
private List<Card> mCards;
3230

33-
private Handler mHandler = new Handler() {
34-
@Override
35-
public void handleMessage(Message msg) {
36-
super.handleMessage(msg);
37-
modifyData();
38-
mHandler.sendEmptyMessageDelayed(0, 2000);
39-
}
40-
};
41-
42-
@Override
43-
protected void onDestroy() {
44-
super.onDestroy();
45-
mHandler.removeMessages(0);
46-
}
31+
private AnimationHelper mHelper;
4732

4833
@Override
4934
protected void onCreate(Bundle savedInstanceState) {
@@ -56,9 +41,6 @@ protected void onCreate(Bundle savedInstanceState) {
5641
mCardStackView.setOnCardClickListener(new CardStackView.OnCardClickListener() {
5742
@Override
5843
public void onClick(View view, int realIndex, int initialIndex) {
59-
//Toast.makeText(MainActivity.this, "点击了第" + realIndex + "个卡片 => " + mCards.get(initialIndex).mTitle,
60-
// Toast.LENGTH_SHORT).show();
61-
6244
toggleAnimation(view, initialIndex);
6345
}
6446
});
@@ -77,30 +59,13 @@ public void onPositionChanged(List<Integer> position) {
7759
mCardAdapter = new SimpleCardAdapter(this, mCards);
7860

7961
mCardStackView.setAdapter(mCardAdapter);
80-
81-
mToolbar.setOnClickListener(new View.OnClickListener() {
82-
@Override
83-
public void onClick(View v) {
84-
recreate();
85-
}
86-
});
8762
}
8863

8964
private List<Card> fakeCards() {
90-
9165
return Arrays.asList(new Card(0xFF2196F3, R.drawable.post, "动态"), new Card(0xFF17B084, R.drawable.task, "任务"),
9266
new Card(0xFFE85D72, R.drawable.calendar, "日程"), new Card(0xFF00BACF, R.drawable.knowledge, "知识"));
9367
}
9468

95-
private void modifyData() {
96-
for (int i = 0; i < mCards.size(); i++) {
97-
mCards.get(i).mTitle += String.valueOf(i);
98-
}
99-
mCardAdapter.notifyDataSetChanged();
100-
}
101-
102-
private AnimationHelper mHelper;
103-
10469
private void toggleAnimation(final View view, final int index) {
10570
mHelper = new AnimationHelper(view, index);
10671

@@ -118,110 +83,75 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
11883
}
11984
}
12085

121-
public void animOtherCards(int idx, boolean reverse) {
122-
for (int i = 0; i < mCardStackView.getChildCount(); i++) {
123-
if (i == idx) continue;
124-
125-
View view = mCardStackView.getChildAt(i);
126-
if (reverse) {
127-
view.animate().translationY(0f).setDuration(AnimationHelper.ANIMATION_DURATION_CARD).start();
128-
} else {
129-
int start = view.getTop();
130-
int end = ((ViewGroup) view.getParent()).getBottom();
131-
view.animate().translationY(end - start).setDuration(AnimationHelper.ANIMATION_DURATION_CARD).start();
132-
}
133-
}
134-
}
135-
13686
private class AnimationHelper {
13787

138-
public int mIndex;
139-
140-
public CardView mCardView;
141-
public TextView mTitle;
142-
public ImageView mImageView;
143-
144-
public int startLeft;
145-
public int endLeft;
146-
public int startRight;
147-
public int endRight;
148-
public int startTop;
149-
public int endTop;
150-
public int startBottom;
151-
public int endBottom;
152-
153-
public int startPaddingLeft;
154-
public int endPaddingLeft;
155-
public int startPaddingRight;
156-
public int endPaddingRight;
157-
public int startPaddingTop;
158-
public int endPaddingTop;
159-
public int startPaddingBottom;
160-
public int endPaddingBottom;
161-
162-
public float startRadius;
163-
public float endRadius;
164-
165-
public @ColorInt int startColor;
166-
public @ColorInt int endColor;
88+
private int mIndex;
89+
90+
private CardView mCardView;
91+
private ImageView mImageView;
92+
private TextView mTitle;
93+
private TextView mFoo;
94+
95+
private int startLeft, endLeft;
96+
private int startRight, endRight;
97+
private int startTop, endTop;
98+
private int startBottom, endBottom;
99+
100+
private float startRadius, endRadius;
101+
102+
private @ColorInt int startColor, endColor;
167103
private ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();
168104

169-
public static final long ANIMATION_DURATION_CARD = 500L;
170-
public static final long ANIMATION_DURATION_ALPHA = 300L;
105+
private float startElevation;
106+
private float endElevation;
107+
108+
private static final long ANIMATION_DURATION_CARD = 500L;
109+
private static final long ANIMATION_DURATION_ALPHA = 300L;
171110

172111
public AnimationHelper(View view, int index) {
173112
mIndex = index;
174113
mCardView = ((CardView) view);
175-
mTitle = (TextView) mCardView.findViewById(R.id.card_title);
176114
mImageView = (ImageView) mCardView.findViewById(R.id.card_image);
115+
mTitle = (TextView) mCardView.findViewById(R.id.card_title);
116+
mFoo = (TextView) mCardView.findViewById(R.id.card_foo);
177117

178118
startLeft = mCardView.getLeft();
179119
startRight = mCardView.getRight();
180120
startTop = mCardView.getTop();
181121
startBottom = mCardView.getBottom();
182122

183-
endLeft = -mCardView.getPaddingLeft();
184-
endRight = mCardView.getWidth() + 2 * mCardView.getLeft() + mCardView.getPaddingRight();
185-
endTop = -mCardView.getPaddingTop();
186-
endBottom = mCardView.getHeight() - mCardView.getPaddingTop();
187-
188-
startPaddingLeft = mCardView.getPaddingLeft();
189-
startPaddingRight = mCardView.getPaddingRight();
190-
startPaddingTop = mCardView.getPaddingTop();
191-
startPaddingBottom = mCardView.getPaddingBottom();
192-
193-
endPaddingLeft = endPaddingRight = endPaddingTop = endPaddingBottom = 0;
123+
endLeft = 0;
124+
endRight = mCardView.getWidth() + 2 * mCardView.getLeft();
125+
endTop = 0;
126+
endBottom = mCardView.getHeight();
194127

195128
startRadius = mCardView.getRadius();
196129
endRadius = 1f;// radius 减到 0 会自动产生透明度变化
197130

198131
startColor = getResources().getColor(R.color.colorPrimaryDark);
199132
endColor = mCards.get(mIndex).mBgColor;
200-
}
201133

202-
public int getLeft(float fraction) {
203-
return (int) (startLeft + fraction * (endLeft - startLeft));
134+
startElevation = mCardView.getMaxCardElevation();
135+
endElevation = 0f;
204136
}
205137

206-
public int getRight(float fraction) {
207-
return (int) (startRight + fraction * (endRight - startRight));
138+
@ColorInt
139+
private int getColor(float fraction) {
140+
return (int) mArgbEvaluator.evaluate(fraction, startColor, endColor);
208141
}
209142

210-
public int getTop(float fraction) {
211-
return (int) (startTop + fraction * (endTop - startTop));
143+
private int getInterpolation(int start, int end, float fraction) {
144+
return (int) (start + fraction * (end - start));
212145
}
213146

214-
public int getBottom(float fraction) {
215-
return (int) (startBottom + fraction * (endBottom - startBottom));
147+
private int getInterpolation(float start, float end, float fraction) {
148+
return (int) (start + fraction * (end - start));
216149
}
217150

218-
public float getRadius(float fraction) {
219-
return startRadius + fraction * (endRadius - startRadius);
220-
}
151+
private float getElevation(float start, float end, float fraction, float threshold) {
152+
if (fraction <= threshold) return start;
221153

222-
@ColorInt
223-
public int getColor(float fraction) {
224-
return (int) mArgbEvaluator.evaluate(fraction, startColor, endColor);
154+
return start + (end - start) * (fraction - threshold) / (1 - threshold);
225155
}
226156

227157
public void startAnimation(final boolean reverse) {
@@ -238,9 +168,11 @@ public void onAnimationUpdate(ValueAnimator animation) {
238168
@Override
239169
public void onAnimationStart(Animator animation) {
240170
mCardStackView.setSkipLayout(true);
171+
mCardStackView.setSkipTouch(true);
241172
if (!reverse) {
242-
mTitle.animate().alpha(0f).setDuration(ANIMATION_DURATION_ALPHA).start();
243173
mToolbar.animate().alpha(0f).setDuration(ANIMATION_DURATION_ALPHA).start();
174+
mTitle.animate().alpha(0f).setDuration(ANIMATION_DURATION_ALPHA).start();
175+
mFoo.animate().alpha(0f).setDuration(ANIMATION_DURATION_ALPHA).start();
244176
}
245177

246178
animOtherCards(mIndex, reverse);
@@ -249,19 +181,20 @@ public void onAnimationStart(Animator animation) {
249181
@Override
250182
public void onAnimationEnd(Animator animation) {
251183
if (reverse) {
252-
mTitle.animate().alpha(1f).setDuration(ANIMATION_DURATION_ALPHA).start();
253184
mToolbar.animate().alpha(1f).setDuration(ANIMATION_DURATION_ALPHA).start();
185+
mTitle.animate().alpha(1f).setDuration(ANIMATION_DURATION_ALPHA).start();
186+
mFoo.animate().alpha(1f).setDuration(ANIMATION_DURATION_ALPHA).start();
254187
} else {
255188
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
256189
intent.putExtra("card", mCards.get(mIndex));
257-
intent.putExtra("padding", startPaddingBottom);
258190
startActivityForResult(intent, REQ_DETAIL);
259191
overridePendingTransition(0, 0);
260192
}
261193
mCardStackView.post(new Runnable() {
262194
@Override
263195
public void run() {
264196
mCardStackView.setSkipLayout(false);
197+
mCardStackView.setSkipTouch(false);
265198
}
266199
});
267200
}
@@ -280,9 +213,25 @@ public void onAnimationRepeat(Animator animation) {
280213
}
281214

282215
private void update(float fraction) {
283-
mCardView.setRadius(getRadius(fraction));
284-
mCardView.getLayoutParams().width = getRight(fraction) - getLeft(fraction);
285-
mCardView.layout(getLeft(fraction), getTop(fraction), getRight(fraction), getBottom(fraction));
216+
mCardView.setRadius(getInterpolation(startRadius, endRadius, fraction));
217+
int right = getInterpolation(startRight, endRight, fraction);
218+
int left = getInterpolation(startLeft, endLeft, fraction);
219+
int top = getInterpolation(startTop, endTop, fraction);
220+
int bottom = getInterpolation(startBottom, endBottom, fraction);
221+
mCardView.getLayoutParams().width = right - left;
222+
mCardView.layout(left, top, right, bottom);
223+
224+
/**
225+
* 设置了一个阈值 threshold, 进度超过阈值之后才开始进行插值。
226+
* 也就是等到其他卡片都收起来之后,再对当前卡片做阴影动画,避免在 5.x 绘制层级问题。
227+
*
228+
* 最终阴影变为0,避免了在 4.x 上 CardView 自带边距绘制阴影,导致无法无缝切换的问题。
229+
*/
230+
float elevation =
231+
getElevation(startElevation, endElevation, fraction, ANIMATION_DURATION_ALPHA * 1f / ANIMATION_DURATION_CARD);
232+
mCardView.setMaxCardElevation(elevation);
233+
mCardView.setCardElevation(elevation);
234+
286235
mCardView.requestLayout();
287236
StatusBarUtil.setColor(MainActivity.this, getColor(fraction));
288237
}
@@ -298,7 +247,26 @@ public void resetViews() {
298247

299248
update(0f);
300249
mTitle.setAlpha(1f);
250+
mFoo.setAlpha(1f);
301251
mToolbar.setAlpha(1f);
302252
}
253+
254+
/**
255+
* 其他卡片直接进行简单的 translation 动画沿 Y 轴移动即可
256+
*/
257+
private void animOtherCards(int idx, boolean reverse) {
258+
for (int i = 0; i < mCardStackView.getChildCount(); i++) {
259+
if (i == idx) continue;
260+
261+
View view = mCardStackView.getChildAt(i);
262+
if (reverse) {
263+
view.animate().translationY(0f).setDuration(AnimationHelper.ANIMATION_DURATION_CARD).start();
264+
} else {
265+
int start = view.getTop();
266+
int end = ((ViewGroup) view.getParent()).getBottom();
267+
view.animate().translationY(end - start).setDuration(AnimationHelper.ANIMATION_DURATION_CARD).start();
268+
}
269+
}
270+
}
303271
}
304272
}

sample/src/main/res/layout/item_card.xml

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
android:layout_height="@dimen/card_height"
99
app:cardCornerRadius="8dp"
1010
app:cardElevation="4dp"
11+
app:cardMaxElevation="4dp"
1112
app:cardPreventCornerOverlap="true"
1213
tools:cardBackgroundColor="#2196F3">
1314

@@ -18,12 +19,34 @@
1819
android:scaleType="centerCrop"
1920
tools:src="@drawable/post"/>
2021

21-
<TextView
22-
android:id="@+id/card_title"
22+
<LinearLayout
2323
android:layout_width="match_parent"
24-
android:layout_height="match_parent"
24+
android:layout_height="wrap_content"
2525
android:layout_margin="16dp"
26-
android:textColor="@android:color/white"
27-
android:textSize="20sp"
28-
tools:text="动态"/>
26+
android:gravity="center_vertical"
27+
android:orientation="horizontal">
28+
29+
<TextView
30+
android:id="@+id/card_title"
31+
android:layout_width="wrap_content"
32+
android:layout_height="wrap_content"
33+
android:textColor="@android:color/white"
34+
android:textSize="20sp"
35+
tools:text="动态"/>
36+
37+
<android.support.v4.widget.Space
38+
android:layout_width="0dp"
39+
android:layout_height="0dp"
40+
android:layout_weight="1"
41+
/>
42+
43+
<TextView
44+
android:id="@+id/card_foo"
45+
android:layout_width="wrap_content"
46+
android:layout_height="wrap_content"
47+
android:text="Foo"
48+
android:textColor="@android:color/white"
49+
/>
50+
</LinearLayout>
51+
2952
</android.support.v7.widget.CardView>

0 commit comments

Comments
 (0)