Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save woshidan/e8703ec975d80d01f80c to your computer and use it in GitHub Desktop.
Save woshidan/e8703ec975d80d01f80c to your computer and use it in GitHub Desktop.
potatotips23_3_points_for_avoid_traps_desgin_support_library
<!-- android.support.design.widget.CollapsingToolbarLayoutのapp:title -->
<!-- を指定していないか、空白の場合と、app:titleEnabled="false"の場合はToolbarのtitleが使われる -->
<!-- app:titleEnabled="false"だとアニメーションしない -->
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="200dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:title=""
app:contentScrim="#fff"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#26e"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"/>
<android.support.v7.widget.Toolbar
android:id="@+id/tool_bar"
app:title="ToolbarTitle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<!-- 見慣れないかもですが、ここはスクロールする要素だったらなんでもよいみたいです -->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<View
android:layout_width="match_parent"
android:layout_height="2000dp"
/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
<!-- * FlotingLabelがTextInputLayoutのものになる -->
<!-- * 通常のhintがEditTextのものになる -->
<!-- * 入力フォームが空のとき、FloatingLabelと通常のhintの両方が表示されてびびる -->
<!-- たぶん通常のonDraw()の後に、
分岐も無くFloatingLabelとして動いている部分のViewの描画処理を呼んでいるせい -->
<!--
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
mCollapsingTextHelper.draw(canvas);
}
-->
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:textColorHint="#0f0"
android:hint="TextInputLayoutWrapper"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#f00"
android:hint="TextInputLayoutEditText"
/>
</android.support.design.widget.TextInputLayout>
// Use the EditText's hint colors if we don't have one set
if (mDefaultTextColor == null) {
mDefaultTextColor = mEditText.getHintTextColors();
}
// If we do not have a valid hint, try and retrieve it from the EditText
if (TextUtils.isEmpty(mHint)) {
setHint(mEditText.getHint());
// Clear the EditText's hint as we will display it ourselves
mEditText.setHint(null);
}
// drawChildrenでも割と目当てのViewがあるか見て処理をしてからデフォの処理を呼び出す、
// というのがあった(CollapsingToolbarLayoutなど)けど、(別のクラスのView等にするために)入れ替えたい要素
// を考える時には、その手前(日本語ならだいたい左上)にある要素を消して入れる必要がある(かそっちの方が早い)
// と覚えておけば良いような気がする。
// Toolbar
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final boolean isRtl = ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL;
final int width = getWidth();
final int height = getHeight();
final int paddingLeft = getPaddingLeft();
final int paddingRight = getPaddingRight();
final int paddingTop = getPaddingTop();
final int paddingBottom = getPaddingBottom();
int left = paddingLeft;
int right = width - paddingRight;
final int[] collapsingMargins = mTempMargins;
collapsingMargins[0] = collapsingMargins[1] = 0;
// Align views within the minimum toolbar height, if set.
final int alignmentHeight = ViewCompat.getMinimumHeight(this);
if (shouldLayout(mNavButtonView)) {
if (isRtl) {
right = layoutChildRight(mNavButtonView, right, collapsingMargins,
alignmentHeight);
} else {
left = layoutChildLeft(mNavButtonView, left, collapsingMargins,
alignmentHeight);
}
}
// right/leftは1つ前に指定した要素の右/左端の位置なので、
// 想定している要素が配置されたとして、
// その隣に順に突っ込むという式になっている
// つまり間が抜けてても左から順番に詰めて配置されるので
// 先に配置された要素を入れ替えたい場合でも後の要素も消す必要がある
if (shouldLayout(mCollapseButtonView)) {
if (isRtl) {
right = layoutChildRight(mCollapseButtonView, right, collapsingMargins,
alignmentHeight);
} else {
left = layoutChildLeft(mCollapseButtonView, left, collapsingMargins,
alignmentHeight);
}
}
if (shouldLayout(mMenuView)) {
if (isRtl) {
left = layoutChildLeft(mMenuView, left, collapsingMargins,
alignmentHeight);
} else {
right = layoutChildRight(mMenuView, right, collapsingMargins,
alignmentHeight);
}
}
collapsingMargins[0] = Math.max(0, getContentInsetLeft() - left);
collapsingMargins[1] = Math.max(0, getContentInsetRight() - (width - paddingRight - right));
left = Math.max(left, getContentInsetLeft());
right = Math.min(right, width - paddingRight - getContentInsetRight());
if (shouldLayout(mExpandedActionView)) {
if (isRtl) {
right = layoutChildRight(mExpandedActionView, right, collapsingMargins,
alignmentHeight);
} else {
left = layoutChildLeft(mExpandedActionView, left, collapsingMargins,
alignmentHeight);
}
}
if (shouldLayout(mLogoView)) {
if (isRtl) {
right = layoutChildRight(mLogoView, right, collapsingMargins,
alignmentHeight);
} else {
left = layoutChildLeft(mLogoView, left, collapsingMargins,
alignmentHeight);
}
}
final boolean layoutTitle = shouldLayout(mTitleTextView);
final boolean layoutSubtitle = shouldLayout(mSubtitleTextView);
int titleHeight = 0;
if (layoutTitle) {
final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
titleHeight += lp.topMargin + mTitleTextView.getMeasuredHeight() + lp.bottomMargin;
}
if (layoutSubtitle) {
final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
titleHeight += lp.topMargin + mSubtitleTextView.getMeasuredHeight() + lp.bottomMargin;
}
if (layoutTitle || layoutSubtitle) {
int titleTop;
final View topChild = layoutTitle ? mTitleTextView : mSubtitleTextView;
final View bottomChild = layoutSubtitle ? mSubtitleTextView : mTitleTextView;
final LayoutParams toplp = (LayoutParams) topChild.getLayoutParams();
final LayoutParams bottomlp = (LayoutParams) bottomChild.getLayoutParams();
final boolean titleHasWidth = layoutTitle && mTitleTextView.getMeasuredWidth() > 0
|| layoutSubtitle && mSubtitleTextView.getMeasuredWidth() > 0;
switch (mGravity & Gravity.VERTICAL_GRAVITY_MASK) {
case Gravity.TOP:
titleTop = getPaddingTop() + toplp.topMargin + mTitleMarginTop;
break;
default:
case Gravity.CENTER_VERTICAL:
final int space = height - paddingTop - paddingBottom;
int spaceAbove = (space - titleHeight) / 2;
if (spaceAbove < toplp.topMargin + mTitleMarginTop) {
spaceAbove = toplp.topMargin + mTitleMarginTop;
} else {
final int spaceBelow = height - paddingBottom - titleHeight -
spaceAbove - paddingTop;
if (spaceBelow < toplp.bottomMargin + mTitleMarginBottom) {
spaceAbove = Math.max(0, spaceAbove -
(bottomlp.bottomMargin + mTitleMarginBottom - spaceBelow));
}
}
titleTop = paddingTop + spaceAbove;
break;
case Gravity.BOTTOM:
titleTop = height - paddingBottom - bottomlp.bottomMargin - mTitleMarginBottom -
titleHeight;
break;
}
if (isRtl) {
final int rd = (titleHasWidth ? mTitleMarginStart : 0) - collapsingMargins[1];
right -= Math.max(0, rd);
collapsingMargins[1] = Math.max(0, -rd);
int titleRight = right;
int subtitleRight = right;
if (layoutTitle) {
final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
final int titleLeft = titleRight - mTitleTextView.getMeasuredWidth();
final int titleBottom = titleTop + mTitleTextView.getMeasuredHeight();
mTitleTextView.layout(titleLeft, titleTop, titleRight, titleBottom);
titleRight = titleLeft - mTitleMarginEnd;
titleTop = titleBottom + lp.bottomMargin;
}
if (layoutSubtitle) {
final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
titleTop += lp.topMargin;
final int subtitleLeft = subtitleRight - mSubtitleTextView.getMeasuredWidth();
final int subtitleBottom = titleTop + mSubtitleTextView.getMeasuredHeight();
mSubtitleTextView.layout(subtitleLeft, titleTop, subtitleRight, subtitleBottom);
subtitleRight = subtitleRight - mTitleMarginEnd;
titleTop = subtitleBottom + lp.bottomMargin;
}
if (titleHasWidth) {
right = Math.min(titleRight, subtitleRight);
}
} else {
final int ld = (titleHasWidth ? mTitleMarginStart : 0) - collapsingMargins[0];
left += Math.max(0, ld);
collapsingMargins[0] = Math.max(0, -ld);
int titleLeft = left;
int subtitleLeft = left;
if (layoutTitle) {
final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
final int titleRight = titleLeft + mTitleTextView.getMeasuredWidth();
final int titleBottom = titleTop + mTitleTextView.getMeasuredHeight();
mTitleTextView.layout(titleLeft, titleTop, titleRight, titleBottom);
titleLeft = titleRight + mTitleMarginEnd;
titleTop = titleBottom + lp.bottomMargin;
}
if (layoutSubtitle) {
final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
titleTop += lp.topMargin;
final int subtitleRight = subtitleLeft + mSubtitleTextView.getMeasuredWidth();
final int subtitleBottom = titleTop + mSubtitleTextView.getMeasuredHeight();
mSubtitleTextView.layout(subtitleLeft, titleTop, subtitleRight, subtitleBottom);
subtitleLeft = subtitleRight + mTitleMarginEnd;
titleTop = subtitleBottom + lp.bottomMargin;
}
if (titleHasWidth) {
left = Math.max(titleLeft, subtitleLeft);
}
}
}
// Get all remaining children sorted for layout. This is all prepared
// such that absolute layout direction can be used below.
addCustomViewsWithGravity(mTempViews, Gravity.LEFT);
final int leftViewsCount = mTempViews.size();
for (int i = 0; i < leftViewsCount; i++) {
left = layoutChildLeft(mTempViews.get(i), left, collapsingMargins,
alignmentHeight);
}
addCustomViewsWithGravity(mTempViews, Gravity.RIGHT);
final int rightViewsCount = mTempViews.size();
for (int i = 0; i < rightViewsCount; i++) {
right = layoutChildRight(mTempViews.get(i), right, collapsingMargins,
alignmentHeight);
}
// Centered views try to center with respect to the whole bar, but views pinned
// to the left or right can push the mass of centered views to one side or the other.
addCustomViewsWithGravity(mTempViews, Gravity.CENTER_HORIZONTAL);
final int centerViewsWidth = getViewListMeasuredWidth(mTempViews, collapsingMargins);
final int parentCenter = paddingLeft + (width - paddingLeft - paddingRight) / 2;
final int halfCenterViewsWidth = centerViewsWidth / 2;
int centerLeft = parentCenter - halfCenterViewsWidth;
final int centerRight = centerLeft + centerViewsWidth;
if (centerLeft < left) {
centerLeft = left;
} else if (centerRight > right) {
centerLeft -= centerRight - right;
}
final int centerViewsCount = mTempViews.size();
for (int i = 0; i < centerViewsCount; i++) {
centerLeft = layoutChildLeft(mTempViews.get(i), centerLeft, collapsingMargins,
alignmentHeight);
}
mTempViews.clear();
}
// InputTextLayout
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mEditText != null) {
final int l = mEditText.getLeft() + mEditText.getCompoundPaddingLeft();
final int r = mEditText.getRight() - mEditText.getCompoundPaddingRight();
mCollapsingTextHelper.setExpandedBounds(l,
mEditText.getTop() + mEditText.getCompoundPaddingTop(),
r, mEditText.getBottom() - mEditText.getCompoundPaddingBottom());
// Set the collapsed bounds to be the the full height (minus padding) to match the
// EditText's editable area
mCollapsingTextHelper.setCollapsedBounds(l, getPaddingTop(),
r, bottom - top - getPaddingBottom());
mCollapsingTextHelper.recalculate();
}
}
// CollapsingToolbarLayout
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// Update our child view offset helpers
for (int i = 0, z = getChildCount(); i < z; i++) {
final View child = getChildAt(i);
if (mLastInsets != null && !ViewCompat.getFitsSystemWindows(child)) {
final int insetTop = mLastInsets.getSystemWindowInsetTop();
if (child.getTop() < insetTop) {
// If the child isn't set to fit system windows but is drawing within the inset
// offset it down
child.offsetTopAndBottom(insetTop);
}
}
getViewOffsetHelper(child).onViewLayout();
}
// Update the collapsed bounds by getting it's transformed bounds
if (mCollapsingTitleEnabled && mDummyView != null) {
ViewGroupUtils.getDescendantRect(this, mDummyView, mTmpRect);
mCollapsingTextHelper.setCollapsedBounds(mTmpRect.left, bottom - mTmpRect.height(),
mTmpRect.right, bottom);
// Update the expanded bounds
mCollapsingTextHelper.setExpandedBounds(
mExpandedMarginLeft,
mTmpRect.bottom + mExpandedMarginTop,
right - left - mExpandedMarginRight,
bottom - top - mExpandedMarginBottom);
mCollapsingTextHelper.recalculate();
}
// Finally, set our minimum height to enable proper AppBarLayout collapsing
if (mToolbar != null) {
if (mCollapsingTitleEnabled && TextUtils.isEmpty(mCollapsingTextHelper.getText())) {
// If we do not currently have a title, try and grab it from the Toolbar
mCollapsingTextHelper.setText(mToolbar.getTitle());
}
setMinimumHeight(mToolbar.getHeight());
}
}
// CollapsingToolbarLayoutの場合
private void animateScrim(int targetAlpha) {
ensureToolbar();
if (mScrimAnimator == null) {
mScrimAnimator = ViewUtils.createAnimator();
mScrimAnimator.setDuration(SCRIM_ANIMATION_DURATION);
mScrimAnimator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
mScrimAnimator.setUpdateListener(new ValueAnimatorCompat.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimatorCompat animator) {
setScrimAlpha(animator.getAnimatedIntValue());
}
});
} else if (mScrimAnimator.isRunning()) {
mScrimAnimator.cancel();
}
mScrimAnimator.setIntValues(mScrimAlpha, targetAlpha);
mScrimAnimator.start();
}
// InputTextLayoutの場合
private static final int ANIMATION_DURATION = 200;
private void collapseHint(boolean animate) {
if (mAnimator != null && mAnimator.isRunning()) {
mAnimator.cancel();
}
if (animate && mHintAnimationEnabled) {
animateToExpansionFraction(1f);
} else {
mCollapsingTextHelper.setExpansionFraction(1f);
}
}
private void animateToExpansionFraction(final float target) {
if (mCollapsingTextHelper.getExpansionFraction() == target) {
return;
}
if (mAnimator == null) {
mAnimator = ViewUtils.createAnimator();
mAnimator.setInterpolator(AnimationUtils.LINEAR_INTERPOLATOR);
mAnimator.setDuration(ANIMATION_DURATION);
mAnimator.setUpdateListener(new ValueAnimatorCompat.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimatorCompat animator) {
mCollapsingTextHelper.setExpansionFraction(animator.getAnimatedFloatValue());
}
});
}
mAnimator.setFloatValues(mCollapsingTextHelper.getExpansionFraction(), target);
mAnimator.start();
}
@woshidan
Copy link
Author

2015-11-24 17 11 37

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment