Add simple dialog curtain

This commit is contained in:
seven332 committed 2015-04-27 23:51:33 +08:00
1 parent 09cda0ce06
commit dd23537302
12 files changed
+386 -16

No files matched your search

@@ -38,6 +38,7 @@ import android.widget.TextView;
import com.hippo.effect.ripple.RippleSalon;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.ListUrlBuilder;
import com.hippo.scene.SimpleDialog;
import com.hippo.util.ViewUtils;
import com.hippo.widget.FloatLabelEditText;
import com.hippo.widget.FloatingActionButton;
@@ -82,6 +83,8 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
private View mNormalView;
private CategoryTable mTableCategory;
private CheckBox mCheckSpecifyAuthor;
private CheckBox mCheckSpecifyTag;
private View mSearchTagHelp;
private SwitchCompat mSwitchEnableAdvance;
private View mAdvanceView;
@@ -157,12 +160,7 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
}
public void setFitPaddingTop(int fitPaddingTop) {
mSearchContainer.setPadding(
mSearchContainer.getPaddingLeft(),
mSearchPaddingTopOrigin + fitPaddingTop,
mSearchContainer.getPaddingRight(),
mSearchContainer.getPaddingBottom()
);
mSearchContainer.setPadding(mSearchContainer.getPaddingLeft(), mSearchPaddingTopOrigin + fitPaddingTop, mSearchContainer.getPaddingRight(), mSearchContainer.getPaddingBottom());
}
public void setFitPaddingBottom(int fitPaddingBottom) {
@@ -260,6 +258,12 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
if (mHelper != null) {
mHelper.onRequestSearch(getListUrlBuilder(null));
}
} else if (v == mSearchTagHelp) {
int[] location = new int [2];
ViewUtils.getLocationInAncestor(mSearchTagHelp, location, R.id.stage);
new SimpleDialog.Builder(getContext()).setTitle(R.string.search_specify_tag)
.setMessage(R.string.search_tag_help)
.setStartPoint(location[0], location[1]).show();
}
}
@@ -404,6 +408,8 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
mNormalView = holder.content.getChildAt(0);
mTableCategory = (CategoryTable) mNormalView.findViewById(R.id.search_category_table);
mCheckSpecifyAuthor = (CheckBox) mNormalView.findViewById(R.id.search_specify_author);
mCheckSpecifyTag = (CheckBox) mNormalView.findViewById(R.id.search_specify_tag);
mSearchTagHelp = mNormalView.findViewById(R.id.search_tag_help);
mSwitchEnableAdvance = (SwitchCompat) mNormalView.findViewById(R.id.search_enable_advance);
// Restore state
@@ -412,6 +418,7 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
}
mCheckSpecifyAuthor.setOnCheckedChangeListener(SearchLayout.this);
mSearchTagHelp.setOnClickListener(SearchLayout.this);
mSwitchEnableAdvance.setOnCheckedChangeListener(SearchLayout.this);
mSwitchEnableAdvance.setSwitchPadding(mResources.getDimensionPixelSize(R.dimen.switch_padding));
} else {
@@ -20,7 +20,7 @@ import android.support.annotation.Nullable;
public abstract class SceneDialog extends Scene {
public void show() {
sSceneManager.showDialog(this, null);
show(null);
}
public void show(@Nullable Curtain curtain) {
@@ -38,7 +38,7 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
private StageActivity mActivity;
private SimpleDialogView mSimpleImageView;
private SimpleDialogView mSimpleDialogView;
private SimpleDialogFrame mFrame;
private View mBody;
private TextView mTitle;
@@ -50,6 +50,7 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
private View mSpacePositiveNegative;
private TextView mPositiveButton;
private int mFitPaddingBottom;
private SimpleDialog(@NonNull Builder builder) {
mBuilder = builder;
@@ -64,12 +65,12 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
mActivity = getStageActivity();
mFrame = new SimpleDialogFrame(mActivity);
setContentView(mFrame);
setContentView(R.layout.simple_dialog_frame);
mFrame = (SimpleDialogFrame) findViewById(R.id.simple_dialog_frame);
mActivity.getLayoutInflater().inflate(R.layout.simple_dialog, mFrame);
mSimpleImageView = (SimpleDialogView) getSceneView();
mSimpleDialogView = (SimpleDialogView) getSceneView();
mBody = findViewById(R.id.body);
mTitle = (TextView) mBody.findViewById(R.id.title);
mSpaceTitleContent = (Space) mBody.findViewById(R.id.space_title_content);
@@ -122,7 +123,7 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
}
}
mSimpleImageView.setOnClickOutOfDialogListener(this);
mSimpleDialogView.setOnClickOutOfDialogListener(this);
}
@Override
@@ -132,9 +133,52 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
@Override
protected void onGetFitPaddingBottom(int b) {
mFitPaddingBottom = b;
mFrame.setFitPaddingBottom(b);
}
public SimpleDialogFrame getFrame() {
return mFrame;
}
public void getCenterLocation(int[] location) {
if (location == null || location.length < 2) {
throw new IllegalArgumentException("location must be an array of two integers");
}
if (mSimpleDialogView == null) {
location[0] = 0;
location[1] = 0;
} else {
location[0] = mSimpleDialogView.getWidth() / 2;
location[1] = (mSimpleDialogView.getHeight() - mFitPaddingBottom) / 2;
}
}
public int getWidth() {
if (mFrame == null) {
return 0;
} else {
return mFrame.getWidth();
}
}
public int getHeight() {
if (mFrame == null) {
return 0;
} else {
return mFrame.getHeight();
}
}
public int getStartX() {
return mBuilder.mStartX;
}
public int getStartY() {
return mBuilder.mStartY;
}
@Override
public void onClick(View v) {
if (v == mPositiveButton) {
@@ -162,6 +206,9 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
private boolean mCancelable = true;
private int mStartX;
private int mStartY;
public Builder(Context context) {
mContext = context;
}
@@ -207,12 +254,25 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
return this;
}
public Builder setStartPoint(int startX, int startY) {
mStartX = startX;
mStartY = startY;
return this;
}
public @NonNull SceneDialog build() {
return new SimpleDialog(this);
}
public void show() {
new SimpleDialog(this).show();
show(null);
}
public void show(Curtain curtain) {
if (curtain == null) {
curtain = new SimpleDialogCurtain(mStartX, mStartY);
}
new SimpleDialog(this).show(curtain);
}
}
}
@@ -0,0 +1,200 @@
/*
* 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.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.ViewTreeObserver;
import com.hippo.animation.ArgbEvaluator;
import com.hippo.animation.SimpleAnimatorListener;
import com.hippo.util.AssertUtils;
import com.hippo.util.ViewUtils;
import java.util.HashSet;
import java.util.Set;
public class SimpleDialogCurtain extends Curtain {
private static long ANIMATE_TIME = 500L;
private int mStartX;
private int mStartY;
private AnimatorSet mAnimatorSet;
public SimpleDialogCurtain() {
this(0, 0);
}
public SimpleDialogCurtain(int startX, int startY) {
mStartX = startX;
mStartY = startY;
}
@Override
public void open(@NonNull final Scene enter, @NonNull final Scene exit) {
AssertUtils.assertInstanceof("SimpleDialogCurtain should only use for SimpleDialog.", enter, SimpleDialog.class);
final SimpleDialog enterDialog = (SimpleDialog) enter;
final Set<Animator> animatorCollection = new HashSet<>();
// Handle background
int bgColor = enter.getBackgroundColor();
int startBgColor = bgColor & 0xffffff;
enter.setBackgroundColor(startBgColor);
ObjectAnimator colorAnim = ObjectAnimator.ofInt(enter, "backgroundColor", bgColor);
colorAnim.setEvaluator(ArgbEvaluator.getInstance());
colorAnim.setDuration(ANIMATE_TIME);
animatorCollection.add(colorAnim);
final View mFrame = enterDialog.getFrame();
AssertUtils.assertNotNull("Frame view must not be null.", mFrame);
ViewUtils.setVisibility(mFrame, View.INVISIBLE);
mFrame.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
ViewUtils.removeOnGlobalLayoutListener(mFrame.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;
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];
} else {
startLeft = mStartX;
startTop = mStartY;
startRight = mStartX;
startBottom = 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);
animatorCollection.add(anim);
mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(animatorCollection);
mAnimatorSet.addListener(new SimpleAnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
ViewUtils.setVisibility(mFrame, View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
dispatchOpenFinished(enter, exit);
mAnimatorSet = null;
}
});
mAnimatorSet.start();
}
});
}
@Override
public void close(@NonNull final Scene enter, @NonNull final Scene exit) {
AssertUtils.assertInstanceof("SimpleDialogCurtain should only use for SimpleDialog.", exit, SimpleDialog.class);
final SimpleDialog exitDialog = (SimpleDialog) exit;
final Set<Animator> animatorCollection = new HashSet<>();
// Handle background
int bgColor = enter.getBackgroundColor();
int endBgColor = bgColor & 0xffffff;
ObjectAnimator colorAnim = ObjectAnimator.ofInt(exit, "backgroundColor", endBgColor);
colorAnim.setEvaluator(ArgbEvaluator.getInstance());
colorAnim.setDuration(ANIMATE_TIME);
animatorCollection.add(colorAnim);
final View mFrame = exitDialog.getFrame();
AssertUtils.assertNotNull("Frame view must not be null.", mFrame);
int startLeft = mFrame.getLeft();
int startTop = mFrame.getTop();
int startRight = mFrame.getRight();
int startBottom = mFrame.getBottom();
int endLeft;
int endTop;
int endRight;
int endBottom;
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];
} else {
endLeft = mStartX;
endTop = mStartY;
endRight = mStartX;
endBottom = 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);
animatorCollection.add(anim);
mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(animatorCollection);
mAnimatorSet.addListener(new SimpleAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
dispatchCloseFinished(enter, exit);
mAnimatorSet = null;
}
});
mAnimatorSet.start();
}
@Override
public void endAnimation() {
if (mAnimatorSet != null) {
mAnimatorSet.end();
}
}
@Override
public boolean isInAnimation() {
return mAnimatorSet != null;
}
}
@@ -32,6 +32,11 @@ public class SimpleDialogFrame extends CardView {
private float mFixedHeightPercent;
private int mFitPaddingBottom;
private int mOriginLeft;
private int mOriginTop;
private int mDrawLeft;
private int mDrawTop;
public SimpleDialogFrame(Context context) {
super(context);
init(context);
@@ -88,4 +93,62 @@ public class SimpleDialogFrame extends CardView {
lp.x = (originalWidth - width) / 2;
lp.y = (originalHeight - mFitPaddingBottom - height) / 2;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mDrawLeft = mOriginLeft = left;
mDrawTop = mOriginTop = top;
}
/**
* I want to set left, but draw start from origin left.
*/
@SuppressWarnings("unused")
public void setDrawLeft(int drawLeft) {
mDrawLeft = drawLeft;
setLeft(drawLeft);
setScrollX(drawLeft - mOriginLeft);
}
@SuppressWarnings("unused")
public int getDrawLeft() {
return mDrawLeft;
}
/**
* I want to set top, but draw start from origin top.
*/
@SuppressWarnings("unused")
public void setDrawTop(int drawTop) {
mDrawTop = drawTop;
setTop(drawTop);
setScrollY((drawTop - mOriginTop));
}
@SuppressWarnings("unused")
public int getDrawTop() {
return mDrawTop;
}
@SuppressWarnings("unused")
public void setDrawRight(int drawRight) {
setRight(drawRight);
}
@SuppressWarnings("unused")
public int getDrawRight() {
return getRight();
}
@SuppressWarnings("unused")
public void setDrawBottom(int drawBottom) {
setBottom(drawBottom);
}
@SuppressWarnings("unused")
public int getDrawBottom() {
return getBottom();
}
}
@@ -72,8 +72,8 @@ public class SimpleDialogView extends SceneView implements View.OnClickListener,
@Override
public void onClick(View v) {
if (v == this && !ViewUtils.isViewUnder(getChildAt(0), (int) mHostpotX, (int) mHostpotY) &&
mOnClickOutOfDialogListener != null) {
if (v == this && !ViewUtils.isViewUnder(getChildAt(0), (int) mHostpotX,
(int) mHostpotY) && mOnClickOutOfDialogListener != null) {
mOnClickOutOfDialogListener.onClickOutOfDialog();
}
}
@@ -35,6 +35,12 @@ public class AssertUtils {
}
}
public static void assertInstanceof(String message, Object obj, Class clazz) {
if (!clazz.isInstance(obj)) {
throw new AssertError(message);
}
}
public static void assertNullEx(String message, Object object)
throws AssertException {
if (object != null) {
@@ -55,4 +61,11 @@ public class AssertUtils {
throw new AssertException(message);
}
}
public static void assertInstanceofEx(String message, Object obj, Class clazz)
throws AssertException {
if (!clazz.isInstance(obj)) {
throw new AssertException(message);
}
}
}