From 3bcb96d89fd696948c4f190a23f6e78d6f62deca Mon Sep 17 00:00:00 2001 From: seven332 Date: Fri, 29 May 2015 00:53:48 +0800 Subject: [PATCH] Optimize SimpleDialogCurtain --- .../java/com/hippo/scene/SceneDialogView.java | 3 +- .../java/com/hippo/scene/SimpleDialog.java | 17 ++- .../com/hippo/scene/SimpleDialogCurtain.java | 131 +++++++++------- .../com/hippo/scene/SimpleDialogFrame.java | 62 +------- .../com/hippo/scene/SimpleDialogLayout.java | 141 ++++++++++++++++++ .../main/res/layout/simple_dialog_frame.xml | 21 ++- 6 files changed, 250 insertions(+), 125 deletions(-) create mode 100644 app/src/main/java/com/hippo/scene/SimpleDialogLayout.java diff --git a/app/src/main/java/com/hippo/scene/SceneDialogView.java b/app/src/main/java/com/hippo/scene/SceneDialogView.java index 57f61a168..8481dd5cd 100644 --- a/app/src/main/java/com/hippo/scene/SceneDialogView.java +++ b/app/src/main/java/com/hippo/scene/SceneDialogView.java @@ -19,6 +19,7 @@ import android.content.Context; import android.os.Build; import android.util.AttributeSet; import android.view.View; +import android.view.ViewGroup; import com.hippo.util.ViewUtils; import com.hippo.widget.HotspotTouchHelper; @@ -72,7 +73,7 @@ public class SceneDialogView extends SceneView implements View.OnClickListener, @Override public void onClick(View v) { - if (v == this && !ViewUtils.isViewUnder(getChildAt(0), (int) mHostpotX, + if (v == this && !ViewUtils.isViewUnder(((ViewGroup) getChildAt(0)).getChildAt(0), (int) mHostpotX, (int) mHostpotY) && mOnClickOutOfDialogListener != null) { mOnClickOutOfDialogListener.onClickOutOfDialog((int) mHostpotX, (int) mHostpotY); } diff --git a/app/src/main/java/com/hippo/scene/SimpleDialog.java b/app/src/main/java/com/hippo/scene/SimpleDialog.java index 88e02b040..91ddb78e4 100644 --- a/app/src/main/java/com/hippo/scene/SimpleDialog.java +++ b/app/src/main/java/com/hippo/scene/SimpleDialog.java @@ -21,7 +21,9 @@ import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StringRes; +import android.support.v7.widget.CardView; import android.view.View; +import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.FrameLayout; @@ -46,6 +48,8 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener, private Builder mBuilder; private SceneDialogView mSceneDialogView; + private SimpleDialogLayout mLayout; + private CardView mCushion; private SimpleDialogFrame mFrame; private View mBody; private TextView mTitle; @@ -73,7 +77,10 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener, setBackgroundColor(BACKGROUND_COLOR); setContentView(R.layout.simple_dialog_frame); - mFrame = (SimpleDialogFrame) findViewById(R.id.simple_dialog_frame); + + mLayout = (SimpleDialogLayout) findViewById(R.id.simple_dialog_layout); + mCushion = (CardView) mLayout.findViewById(R.id.simple_dialog_cushion); + mFrame = (SimpleDialogFrame) mLayout.findViewById(R.id.simple_dialog_frame); getStageActivity().getLayoutInflater().inflate(R.layout.simple_dialog, mFrame); @@ -181,10 +188,14 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener, @Override protected void onGetFitPaddingBottom(int b) { mFitPaddingBottom = b; - mFrame.setFitPaddingBottom(b); + mLayout.setFitPaddingBottom(b); } - public SimpleDialogFrame getFrame() { + public CardView getCushion() { + return mCushion; + } + + public ViewGroup getFrame() { return mFrame; } diff --git a/app/src/main/java/com/hippo/scene/SimpleDialogCurtain.java b/app/src/main/java/com/hippo/scene/SimpleDialogCurtain.java index 77a588905..288a05645 100644 --- a/app/src/main/java/com/hippo/scene/SimpleDialogCurtain.java +++ b/app/src/main/java/com/hippo/scene/SimpleDialogCurtain.java @@ -78,55 +78,64 @@ public class SimpleDialogCurtain extends Curtain { colorAnim.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); animatorCollection.add(colorAnim); - final View mFrame = enterDialog.getFrame(); - AssertUtils.assertNotNull("Frame view must not be null.", mFrame); + final View cushion = enterDialog.getCushion(); + final View frame = enterDialog.getFrame(); + AssertUtils.assertNotNull("Cushion view must not be null.", cushion); + AssertUtils.assertNotNull("Frame view must not be null.", frame); - ViewUtils.setVisibility(mFrame, View.INVISIBLE); + ViewUtils.setVisibility(cushion, View.INVISIBLE); + ViewUtils.setVisibility(frame, View.INVISIBLE); - mFrame.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + frame.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { - ViewUtils.removeOnGlobalLayoutListener(mFrame.getViewTreeObserver(), this); + ViewUtils.removeOnGlobalLayoutListener(frame.getViewTreeObserver(), this); - int endLeft = mFrame.getLeft(); - int endTop = mFrame.getTop(); - int endRight = mFrame.getRight(); - int endBottom = mFrame.getBottom(); - int startLeft; - int startTop; - int startRight; - int startBottom; + float floatStartX; + float floatStartY; + int intStartX; + int intStartY; if (mStartX == 0 && mStartY == 0) { int[] center = new int[2]; enterDialog.getCenterLocation(center); - startLeft = center[0]; - startTop = center[1]; - startRight = center[0]; - startBottom = center[1]; + floatStartX = center[0]; + floatStartY = center[1]; + intStartX = center[0]; + intStartY = center[1]; } else { - startLeft = mStartX; - startTop = mStartY; - startRight = mStartX; - startBottom = mStartY; + floatStartX = mStartX; + floatStartY = mStartY; + intStartX = mStartX; + intStartY = mStartY; } - // TODO should start from frame edge when it is out of frame - PropertyValuesHolder leftPvh = PropertyValuesHolder.ofInt("drawLeft", startLeft, endLeft); - PropertyValuesHolder topPvh = PropertyValuesHolder.ofInt("drawTop", startTop, endTop); - PropertyValuesHolder rightPvh = PropertyValuesHolder.ofInt("drawRight", startRight, endRight); - PropertyValuesHolder bottomPvh = PropertyValuesHolder.ofInt("drawBottom", startBottom, endBottom); - ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(mFrame, leftPvh, topPvh, rightPvh, bottomPvh); - anim.setDuration(ANIMATE_TIME); - anim.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + cushion.setPivotX(0f); + cushion.setPivotY(0f); + PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f); + PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f); + PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", floatStartX, frame.getLeft()); + PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", floatStartY, frame.getTop()); + ObjectAnimator animCushion = ObjectAnimator.ofPropertyValuesHolder(cushion, scaleXPvh, scaleYPvh, xPvh, yPvh); + animCushion.setDuration(ANIMATE_TIME); + animCushion.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + animatorCollection.add(animCushion); - animatorCollection.add(anim); + PropertyValuesHolder leftPvh = PropertyValuesHolder.ofInt("drawLeft", intStartX, frame.getLeft()); + PropertyValuesHolder topPvh = PropertyValuesHolder.ofInt("drawTop", intStartY, frame.getTop()); + PropertyValuesHolder rightPvh = PropertyValuesHolder.ofInt("drawRight", intStartX, frame.getRight()); + PropertyValuesHolder bottomPvh = PropertyValuesHolder.ofInt("drawBottom", intStartY, frame.getBottom()); + ObjectAnimator animFrame = ObjectAnimator.ofPropertyValuesHolder(frame, leftPvh, topPvh, rightPvh, bottomPvh); + animFrame.setDuration(ANIMATE_TIME); + animFrame.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + animatorCollection.add(animFrame); mAnimatorSet = new AnimatorSet(); mAnimatorSet.playTogether(animatorCollection); mAnimatorSet.addListener(new SimpleAnimatorListener() { @Override public void onAnimationStart(Animator animation) { - ViewUtils.setVisibility(mFrame, View.VISIBLE); + ViewUtils.setVisibility(cushion, View.VISIBLE); + ViewUtils.setVisibility(frame, View.VISIBLE); } @Override public void onAnimationEnd(Animator animation) { @@ -155,40 +164,48 @@ public class SimpleDialogCurtain extends Curtain { animatorCollection.add(colorAnim); colorAnim.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR); - final View mFrame = exitDialog.getFrame(); - AssertUtils.assertNotNull("Frame view must not be null.", mFrame); + final View cushion = exitDialog.getCushion(); + final View frame = exitDialog.getFrame(); + AssertUtils.assertNotNull("Cushion view must not be null.", cushion); + AssertUtils.assertNotNull("Frame view must not be null.", frame); - int startLeft = mFrame.getLeft(); - int startTop = mFrame.getTop(); - int startRight = mFrame.getRight(); - int startBottom = mFrame.getBottom(); - int endLeft; - int endTop; - int endRight; - int endBottom; + float floatEndX; + float floatEndY; + int intEndX; + int intEndY; if (mStartX == 0 && mStartY == 0) { int[] center = new int[2]; exitDialog.getCenterLocation(center); - endLeft = center[0]; - endTop = center[1]; - endRight = center[0]; - endBottom = center[1]; + floatEndX = center[0]; + floatEndY = center[1]; + intEndX = center[0]; + intEndY = center[1]; } else { - endLeft = mStartX; - endTop = mStartY; - endRight = mStartX; - endBottom = mStartY; + floatEndX = mStartX; + floatEndY = mStartY; + intEndX = mStartX; + intEndY = mStartY; } - PropertyValuesHolder leftPvh = PropertyValuesHolder.ofInt("drawLeft", startLeft, endLeft); - PropertyValuesHolder topPvh = PropertyValuesHolder.ofInt("drawTop", startTop, endTop); - PropertyValuesHolder rightPvh = PropertyValuesHolder.ofInt("drawRight", startRight, endRight); - PropertyValuesHolder bottomPvh = PropertyValuesHolder.ofInt("drawBottom", startBottom, endBottom); - ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(mFrame, leftPvh, topPvh, rightPvh, bottomPvh); - anim.setDuration(ANIMATE_TIME); - anim.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR); + cushion.setPivotX(0f); + cushion.setPivotY(0f); + PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", 0f); + PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", 0f); + PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", floatEndX); + PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", floatEndY); + ObjectAnimator animCushion = ObjectAnimator.ofPropertyValuesHolder(cushion, scaleXPvh, scaleYPvh, xPvh, yPvh); + animCushion.setDuration(ANIMATE_TIME); + animCushion.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + animatorCollection.add(animCushion); - animatorCollection.add(anim); + PropertyValuesHolder leftPvh = PropertyValuesHolder.ofInt("drawLeft", intEndX); + PropertyValuesHolder topPvh = PropertyValuesHolder.ofInt("drawTop", intEndY); + PropertyValuesHolder rightPvh = PropertyValuesHolder.ofInt("drawRight", intEndX); + PropertyValuesHolder bottomPvh = PropertyValuesHolder.ofInt("drawBottom", intEndY); + ObjectAnimator animFrame = ObjectAnimator.ofPropertyValuesHolder(frame, leftPvh, topPvh, rightPvh, bottomPvh); + animFrame.setDuration(ANIMATE_TIME); + animFrame.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + animatorCollection.add(animFrame); mAnimatorSet = new AnimatorSet(); mAnimatorSet.playTogether(animatorCollection); diff --git a/app/src/main/java/com/hippo/scene/SimpleDialogFrame.java b/app/src/main/java/com/hippo/scene/SimpleDialogFrame.java index f47409e6b..64166a580 100644 --- a/app/src/main/java/com/hippo/scene/SimpleDialogFrame.java +++ b/app/src/main/java/com/hippo/scene/SimpleDialogFrame.java @@ -16,22 +16,10 @@ package com.hippo.scene; import android.content.Context; -import android.content.res.Resources; -import android.support.v7.widget.CardView; import android.util.AttributeSet; -import android.view.RenderNodeAnimator; -import android.widget.AbsoluteLayout; +import android.widget.FrameLayout; -import com.hippo.ehviewer.R; -import com.hippo.util.ResourcesUtils; - -public class SimpleDialogFrame extends CardView { - - private int mPadding; - private int mFixedWidth; - private float mFixedWidthPercent; - private float mFixedHeightPercent; - private int mFitPaddingBottom; +public class SimpleDialogFrame extends FrameLayout { private int mOriginLeft; private int mOriginTop; @@ -40,59 +28,14 @@ public class SimpleDialogFrame extends CardView { public SimpleDialogFrame(Context context) { super(context); - init(context); } public SimpleDialogFrame(Context context, AttributeSet attrs) { super(context, attrs); - init(context); } public SimpleDialogFrame(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - init(context); - } - - private void init(Context context) { - Resources resources = context.getResources(); - mPadding = resources.getDimensionPixelOffset(R.dimen.simple_dialog_padding); - mFixedWidth = resources.getDimensionPixelOffset(R.dimen.simple_dialog_fixed_width); - mFixedWidthPercent = ResourcesUtils.getFloat(resources, R.dimen.simple_dialog_fixed_width_percent); - mFixedHeightPercent = ResourcesUtils.getFloat(resources, R.dimen.simple_dialog_fixed_height_percent); - } - - public void setFitPaddingBottom(int fitPaddingBottom) { - if (mFitPaddingBottom != fitPaddingBottom) { - mFitPaddingBottom = fitPaddingBottom; - requestLayout(); - } - } - - @SuppressWarnings("deprecation") - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // Width - int originalWidth = MeasureSpec.getSize(widthMeasureSpec); - if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) { - int fixedWidth = Math.min((int) (originalWidth * mFixedWidthPercent), mFixedWidth) - - (2 * mPadding); - widthMeasureSpec = MeasureSpec.makeMeasureSpec(fixedWidth, MeasureSpec.EXACTLY); - } - // Height - int originalHeight = MeasureSpec.getSize(heightMeasureSpec); - if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.UNSPECIFIED) { - int fixedHeight = (int) ((originalHeight - mFitPaddingBottom) * mFixedHeightPercent) - - (2 * mPadding); - heightMeasureSpec = MeasureSpec.makeMeasureSpec(fixedHeight, MeasureSpec.AT_MOST); - } - // Measure - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - // Update x, y - int width = getMeasuredWidth(); - int height = getMeasuredHeight(); - AbsoluteLayout.LayoutParams lp = (AbsoluteLayout.LayoutParams) getLayoutParams(); - lp.x = (originalWidth - width) / 2; - lp.y = (originalHeight - mFitPaddingBottom - height) / 2; } @Override @@ -111,7 +54,6 @@ public class SimpleDialogFrame extends CardView { mDrawLeft = drawLeft; setLeft(drawLeft); setScrollX(drawLeft - mOriginLeft); - RenderNodeAnimator animato; } @SuppressWarnings("unused") diff --git a/app/src/main/java/com/hippo/scene/SimpleDialogLayout.java b/app/src/main/java/com/hippo/scene/SimpleDialogLayout.java new file mode 100644 index 000000000..203461033 --- /dev/null +++ b/app/src/main/java/com/hippo/scene/SimpleDialogLayout.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.scene; + +import android.content.Context; +import android.content.res.Resources; +import android.support.annotation.NonNull; +import android.support.v7.widget.CardView; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +import com.hippo.ehviewer.R; +import com.hippo.util.ResourcesUtils; + +public class SimpleDialogLayout extends ViewGroup { + + private int mPadding; + private int mFixedWidth; + private float mFixedWidthPercent; + private float mFixedHeightPercent; + private int mFitPaddingBottom; + + private CardView mCushion; + private ViewGroup mFrame; + + public SimpleDialogLayout(Context context) { + super(context); + init(context); + } + + public SimpleDialogLayout(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public SimpleDialogLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + Resources resources = context.getResources(); + mPadding = resources.getDimensionPixelOffset(R.dimen.simple_dialog_padding); + mFixedWidth = resources.getDimensionPixelOffset(R.dimen.simple_dialog_fixed_width); + mFixedWidthPercent = ResourcesUtils.getFloat(resources, R.dimen.simple_dialog_fixed_width_percent); + mFixedHeightPercent = ResourcesUtils.getFloat(resources, R.dimen.simple_dialog_fixed_height_percent); + } + + @Override + public final void addView(@NonNull View child, int index, ViewGroup.LayoutParams params) { + super.addView(child, index, params); + + if (child instanceof CardView) { + if (mCushion != null) { + throw new IllegalStateException("Only need one cushion in SimpleDialog"); + } + mCushion = (CardView) child; + if (mFrame != null) { + mFrame.setPadding(mCushion.getPaddingLeft(), + mCushion.getPaddingTop(), mCushion.getPaddingRight(), + mCushion.getPaddingBottom()); + } + } else { + if (mFrame != null) { + throw new IllegalStateException("Only need one frame in SimpleDialog"); + } + mFrame = (ViewGroup) child; + if (mCushion != null) { + mFrame.setPadding(mCushion.getPaddingLeft(), + mCushion.getPaddingTop(), mCushion.getPaddingRight(), + mCushion.getPaddingBottom()); + } + } + } + + public void setFitPaddingBottom(int fitPaddingBottom) { + if (mFitPaddingBottom != fitPaddingBottom) { + mFitPaddingBottom = fitPaddingBottom; + requestLayout(); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int newWidthMeasureSpec; + int newHeightMeasureSpec; + // Width + int originalWidth = MeasureSpec.getSize(widthMeasureSpec); + if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) { + int fixedWidth = Math.min((int) (originalWidth * mFixedWidthPercent), mFixedWidth) - + (2 * mPadding); + newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(fixedWidth, MeasureSpec.EXACTLY); + } else { + throw new IllegalStateException("MeasureSpec.UNSPECIFIED is not allowed in SimpleDialogLayout"); + } + // Height + int originalHeight = MeasureSpec.getSize(heightMeasureSpec); + if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.UNSPECIFIED) { + int fixedHeight = (int) ((originalHeight - mFitPaddingBottom) * mFixedHeightPercent) - + (2 * mPadding); + newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(fixedHeight, MeasureSpec.AT_MOST); + } else { + throw new IllegalStateException("MeasureSpec.UNSPECIFIED is not allowed in SimpleDialogLayout"); + } + + measureChild(mFrame, newWidthMeasureSpec, newHeightMeasureSpec); + measureChild(mCushion, + MeasureSpec.makeMeasureSpec(mFrame.getMeasuredWidth(), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(mFrame.getMeasuredHeight(), MeasureSpec.EXACTLY)); + + setMeasuredDimension(originalWidth, originalHeight); + } + + private void layoutChild(View child) { + int childWidth = child.getMeasuredWidth(); + int childHeight = child.getMeasuredHeight(); + int left = (getWidth() / 2) - (childWidth / 2); + int top = ((getHeight() - mFitPaddingBottom) / 2) - (childHeight / 2); + child.layout(left, top, left + childWidth, top + childHeight); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + layoutChild(mCushion); + layoutChild(mFrame); + } +} diff --git a/app/src/main/res/layout/simple_dialog_frame.xml b/app/src/main/res/layout/simple_dialog_frame.xml index 8b79c6eac..038ca32f1 100644 --- a/app/src/main/res/layout/simple_dialog_frame.xml +++ b/app/src/main/res/layout/simple_dialog_frame.xml @@ -13,10 +13,23 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + android:layout_height="match_parent"> + + + + + + +