Add simple dialog curtain
This commit is contained in:
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user