From 09cda0ce06d678cde65f8f49b02fb6d6e640f8f6 Mon Sep 17 00:00:00 2001 From: seven332 Date: Mon, 27 Apr 2015 16:46:25 +0800 Subject: [PATCH] Update scene dialog --- .../com/hippo/effect/ripple/RippleSalon.java | 9 +- .../ehviewer/ui/scene/GalleryListScene.java | 9 -- app/src/main/java/com/hippo/scene/Scene.java | 11 +- .../main/java/com/hippo/scene/SceneView.java | 47 ++++++ .../java/com/hippo/scene/SimpleDialog.java | 141 +++++++++++++++++- .../com/hippo/scene/SimpleDialogView.java | 84 +++++++++++ .../main/java/com/hippo/util/ViewUtils.java | 2 +- .../hippo/widget/IndicatingScrollView.java | 92 ++++++++++++ .../com/hippo/widget/NotifyingScrollView.java | 50 +++++++ .../hippo/widget/OnScrollChangeListener.java | 35 +++++ app/src/main/res/layout/simple_dialog.xml | 39 +++-- app/src/main/res/values/colors.xml | 6 +- app/src/main/res/values/dimens.xml | 9 ++ app/src/main/res/values/styles.xml | 14 +- 14 files changed, 505 insertions(+), 43 deletions(-) create mode 100644 app/src/main/java/com/hippo/scene/SceneView.java create mode 100644 app/src/main/java/com/hippo/scene/SimpleDialogView.java create mode 100644 app/src/main/java/com/hippo/widget/IndicatingScrollView.java create mode 100644 app/src/main/java/com/hippo/widget/NotifyingScrollView.java create mode 100644 app/src/main/java/com/hippo/widget/OnScrollChangeListener.java diff --git a/app/src/main/java/com/hippo/effect/ripple/RippleSalon.java b/app/src/main/java/com/hippo/effect/ripple/RippleSalon.java index 4766be02c..242d0fb7d 100644 --- a/app/src/main/java/com/hippo/effect/ripple/RippleSalon.java +++ b/app/src/main/java/com/hippo/effect/ripple/RippleSalon.java @@ -28,8 +28,6 @@ import com.hippo.widget.HotspotTouchHelper; public final class RippleSalon { - private static final Drawable MASK = new ColorDrawable(Color.BLACK); - public static void addRipple(View c, boolean dark) { Resources resources = c.getContext().getResources(); ColorStateList color = ColorStateList.valueOf( @@ -41,17 +39,16 @@ public final class RippleSalon { addRipple(v, color, v.getBackground()); } + @SuppressWarnings("deprecation") public static void addRipple(View v, ColorStateList color, Drawable content) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { RippleDrawable rippleDrawable = new RippleDrawable(color, content); v.setOnTouchListener(new HotspotTouchHelper(rippleDrawable)); - //noinspection deprecation v.setBackgroundDrawable(rippleDrawable); } else { android.graphics.drawable.RippleDrawable rippleDrawable = - new android.graphics.drawable.RippleDrawable(color, content, MASK); - //noinspection deprecation - v.setBackgroundDrawable(rippleDrawable); + new android.graphics.drawable.RippleDrawable(color, content, new ColorDrawable(Color.BLACK)); + v.setBackground(rippleDrawable); } } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index 30b6e1e90..b0fb232c2 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -28,8 +28,6 @@ import com.hippo.ehviewer.widget.SearchBar; import com.hippo.ehviewer.widget.SearchDatabase; import com.hippo.ehviewer.widget.SearchLayout; import com.hippo.scene.Scene; -import com.hippo.scene.SimpleDialog; -import com.hippo.util.AppHandler; import com.hippo.util.Log; import com.hippo.util.ViewUtils; @@ -79,13 +77,6 @@ class GalleryListScene extends Scene implements SearchBar.Helper { // TEST mContentLayout.showText("四姑拉斯基"); - - AppHandler.getInstance().postDelayed(new Runnable() { - @Override - public void run() { - new SimpleDialog.Builder().setTitle("NIhao").show(); - } - }, 2000); } @Override diff --git a/app/src/main/java/com/hippo/scene/Scene.java b/app/src/main/java/com/hippo/scene/Scene.java index 6a0aa4d4b..14d11a171 100644 --- a/app/src/main/java/com/hippo/scene/Scene.java +++ b/app/src/main/java/com/hippo/scene/Scene.java @@ -26,7 +26,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; -import android.widget.AbsoluteLayout; import android.widget.FrameLayout; import com.hippo.util.AssertUtils; @@ -52,7 +51,7 @@ public abstract class Scene { private @Nullable Announcer mAnnouncer; @SuppressWarnings("deprecation") - private @Nullable AbsoluteLayout mSceneView; + private @Nullable SceneView mSceneView; private int mBackgroundColor = 0xffeeeeee; // TODO Need a better to set background color @@ -94,7 +93,7 @@ public abstract class Scene { * * @return Null or nonull */ - public @Nullable ViewGroup getSceneView() { + public @Nullable SceneView getSceneView() { return mSceneView; } @@ -119,9 +118,8 @@ public abstract class Scene { mState = state; } - @SuppressWarnings("deprecation") - protected AbsoluteLayout createSceneView(Context context) { - return new AbsoluteLayout(context); + protected SceneView createSceneView(Context context) { + return new SceneView(context); } public final void finish() { @@ -221,7 +219,6 @@ public abstract class Scene { private void initBackground(@NonNull View bg) { bg.setBackgroundColor(mBackgroundColor); - bg.setClickable(true); bg.setFocusable(true); bg.setFocusableInTouchMode(true); bg.requestFocus(); diff --git a/app/src/main/java/com/hippo/scene/SceneView.java b/app/src/main/java/com/hippo/scene/SceneView.java new file mode 100644 index 000000000..a35b5728f --- /dev/null +++ b/app/src/main/java/com/hippo/scene/SceneView.java @@ -0,0 +1,47 @@ +/* + * 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.util.AttributeSet; +import android.widget.AbsoluteLayout; + +@SuppressWarnings("deprecation") +public class SceneView extends AbsoluteLayout { + public SceneView(Context context) { + super(context); + init(); + } + + public SceneView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public SceneView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + setClickable(true); + } + + @Override + protected void dispatchSetPressed(boolean pressed) { + // Don't dispatch it to children + } +} diff --git a/app/src/main/java/com/hippo/scene/SimpleDialog.java b/app/src/main/java/com/hippo/scene/SimpleDialog.java index 4fa102270..c94cb30b4 100644 --- a/app/src/main/java/com/hippo/scene/SimpleDialog.java +++ b/app/src/main/java/com/hippo/scene/SimpleDialog.java @@ -15,14 +15,22 @@ package com.hippo.scene; +import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.view.View; +import android.widget.Space; import android.widget.TextView; +import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.R; +import com.hippo.util.ViewUtils; +import com.hippo.widget.IndicatingScrollView; -public class SimpleDialog extends SceneDialog { +public class SimpleDialog extends SceneDialog implements View.OnClickListener, + SimpleDialogView.OnClickOutOfDialogListener { private static final int BACKGROUND_COLOR = 0x61000000; @@ -30,10 +38,20 @@ public class SimpleDialog extends SceneDialog { private StageActivity mActivity; + private SimpleDialogView mSimpleImageView; private SimpleDialogFrame mFrame; + private View mBody; private TextView mTitle; + private Space mSpaceTitleContent; + private IndicatingScrollView mContent; + private TextView mMessage; + private View mButtonsSingleLine; + private TextView mNegativeButton; + private View mSpacePositiveNegative; + private TextView mPositiveButton; - private SimpleDialog(Builder builder) { + + private SimpleDialog(@NonNull Builder builder) { mBuilder = builder; } @@ -51,13 +69,65 @@ public class SimpleDialog extends SceneDialog { mActivity.getLayoutInflater().inflate(R.layout.simple_dialog, mFrame); - mTitle = (TextView) findViewById(R.id.title); + mSimpleImageView = (SimpleDialogView) getSceneView(); + mBody = findViewById(R.id.body); + mTitle = (TextView) mBody.findViewById(R.id.title); + mSpaceTitleContent = (Space) mBody.findViewById(R.id.space_title_content); + mContent = (IndicatingScrollView) findViewById(R.id.content); + mMessage = (TextView) mBody.findViewById(R.id.message); + mButtonsSingleLine = findViewById(R.id.buttons_single_line); + mNegativeButton = (TextView) mButtonsSingleLine.findViewById(R.id.negative); + mSpacePositiveNegative = mButtonsSingleLine.findViewById(R.id.space_positive_negative); + mPositiveButton = (TextView) mButtonsSingleLine.findViewById(R.id.positive); bindDialog(); } private void bindDialog() { - mTitle.setText(mBuilder.mTitle); + if (mBuilder.mTitle == null && mBuilder.mMessage == null) { + ViewUtils.setVisibility(mBody, View.GONE); + } else { + if (mBuilder.mTitle != null) { + mTitle.setText(mBuilder.mTitle); + } else { + ViewUtils.setVisibility(mTitle, View.GONE); + ViewUtils.setVisibility(mSpaceTitleContent, View.GONE); + } + if (mBuilder.mMessage != null) { + mMessage.setText(mBuilder.mMessage); + } else { + ViewUtils.setVisibility(mContent, View.GONE); + ViewUtils.setVisibility(mSpaceTitleContent, View.GONE); + } + } + + if (mBuilder.mPositiveButtonText == null && mBuilder.mNegativeButtonText == null) { + ViewUtils.setVisibility(mButtonsSingleLine, View.GONE); + } else { + if (mBuilder.mPositiveButtonText != null) { + mPositiveButton.setText(mBuilder.mPositiveButtonText); + mPositiveButton.setOnClickListener(this); + RippleSalon.addRipple(mPositiveButton, false); + } else { + ViewUtils.setVisibility(mPositiveButton, View.GONE); + ViewUtils.setVisibility(mSpacePositiveNegative, View.GONE); + } + if (mBuilder.mNegativeButtonText != null) { + mNegativeButton.setText(mBuilder.mNegativeButtonText); + mNegativeButton.setOnClickListener(this); + RippleSalon.addRipple(mNegativeButton, false); + } else { + ViewUtils.setVisibility(mNegativeButton, View.GONE); + ViewUtils.setVisibility(mSpacePositiveNegative, View.GONE); + } + } + + mSimpleImageView.setOnClickOutOfDialogListener(this); + } + + @Override + protected SceneView createSceneView(Context context) { + return new SimpleDialogView(context); } @Override @@ -65,15 +135,78 @@ public class SimpleDialog extends SceneDialog { mFrame.setFitPaddingBottom(b); } + @Override + public void onClick(View v) { + if (v == mPositiveButton) { + finish(); + } else if (v == mNegativeButton) { + finish(); + } + } + + @Override + public void onClickOutOfDialog() { + if (mBuilder.mCancelable) { + finish(); + } + } + public static class Builder { + private Context mContext; + private String mTitle; + private String mMessage; + private String mPositiveButtonText; + private String mNegativeButtonText; + + private boolean mCancelable = true; + + public Builder(Context context) { + mContext = context; + } public Builder setTitle(String title) { mTitle = title; return this; } + public Builder setTitle(@StringRes int resId) { + return setTitle(mContext.getString(resId)); + } + + public Builder setMessage(String message) { + mMessage = message; + return this; + } + + public Builder setMessage(@StringRes int resId) { + return setMessage(mContext.getString(resId)); + } + + public Builder setPositiveButton(String string) { + mPositiveButtonText = string; + return this; + } + + public Builder setPositiveButton(int resId) { + return setPositiveButton(mContext.getString(resId)); + } + + public Builder setNegativeButton(String string) { + mNegativeButtonText = string; + return this; + } + + public Builder setNegativeButton(int resId) { + return setNegativeButton(mContext.getString(resId)); + } + + public Builder setCancelable(boolean cancelable) { + mCancelable = cancelable; + return this; + } + public @NonNull SceneDialog build() { return new SimpleDialog(this); } diff --git a/app/src/main/java/com/hippo/scene/SimpleDialogView.java b/app/src/main/java/com/hippo/scene/SimpleDialogView.java new file mode 100644 index 000000000..82c136a08 --- /dev/null +++ b/app/src/main/java/com/hippo/scene/SimpleDialogView.java @@ -0,0 +1,84 @@ +/* + * 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.os.Build; +import android.util.AttributeSet; +import android.view.View; + +import com.hippo.util.ViewUtils; +import com.hippo.widget.HotspotTouchHelper; +import com.hippo.widget.Hotspotable; + +public class SimpleDialogView extends SceneView implements View.OnClickListener, Hotspotable { + + private float mHostpotX; + private float mHostpotY; + + private OnClickOutOfDialogListener mOnClickOutOfDialogListener; + + public SimpleDialogView(Context context) { + super(context); + init(); + } + + public SimpleDialogView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public SimpleDialogView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + setSoundEffectsEnabled(false); + setOnClickListener(this); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + setOnTouchListener(new HotspotTouchHelper(this)); + } + } + + public void setOnClickOutOfDialogListener(OnClickOutOfDialogListener listener) { + mOnClickOutOfDialogListener = listener; + } + + @Override + public void setHotspot(float x, float y) { + mHostpotX = x; + mHostpotY = y; + } + + @Override + public void drawableHotspotChanged(float x, float y) { + mHostpotX = x; + mHostpotY = y; + } + + @Override + public void onClick(View v) { + if (v == this && !ViewUtils.isViewUnder(getChildAt(0), (int) mHostpotX, (int) mHostpotY) && + mOnClickOutOfDialogListener != null) { + mOnClickOutOfDialogListener.onClickOutOfDialog(); + } + } + + public interface OnClickOutOfDialogListener { + void onClickOutOfDialog(); + } +} diff --git a/app/src/main/java/com/hippo/util/ViewUtils.java b/app/src/main/java/com/hippo/util/ViewUtils.java index 96f9927ba..d4ed77ac6 100644 --- a/app/src/main/java/com/hippo/util/ViewUtils.java +++ b/app/src/main/java/com/hippo/util/ViewUtils.java @@ -244,7 +244,7 @@ public final class ViewUtils { * @param y Y position to test in the parent's coordinate system * @return true if the supplied view is under the given point, false otherwise */ - public static boolean isViewUnder(View view, int x, int y) { + public static boolean isViewUnder(@Nullable View view, int x, int y) { if (view == null || view.getVisibility() != View.VISIBLE) { return false; } diff --git a/app/src/main/java/com/hippo/widget/IndicatingScrollView.java b/app/src/main/java/com/hippo/widget/IndicatingScrollView.java new file mode 100644 index 000000000..dadad76b2 --- /dev/null +++ b/app/src/main/java/com/hippo/widget/IndicatingScrollView.java @@ -0,0 +1,92 @@ +/* + * 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.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.annotation.NonNull; +import android.util.AttributeSet; +import android.widget.ScrollView; + +import com.hippo.ehviewer.R; + +public class IndicatingScrollView extends ScrollView { + + private int mIndicatorHeight; + + private Paint mPaint = new Paint(); + private Rect mTemp = new Rect(); + + public IndicatingScrollView(Context context) { + super(context); + init(context); + } + + public IndicatingScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public IndicatingScrollView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + mIndicatorHeight = context.getResources().getDimensionPixelOffset(R.dimen.scroll_view_indicator_height); + mPaint.setColor(context.getResources().getColor(R.color.scroll_view_indicator)); + mPaint.setStyle(Paint.Style.FILL); + } + + private void fillTopIndicatorDrawRect() { + mTemp.set(0, 0, getWidth(), mIndicatorHeight); + } + + private void fillBottomIndicatorDrawRect() { + mTemp.set(0, getHeight() - mIndicatorHeight, getWidth(), getHeight()); + } + + private boolean needShowTopIndicator() { + return canScrollVertically(-1); + } + + private boolean needShowBottomIndicator() { + return canScrollVertically(1); + } + + @Override + public void draw(@NonNull Canvas canvas) { + super.draw(canvas); + + final int restoreCount = canvas.save(); + canvas.translate(getScrollX(), getScrollY()); + + // Draw top indicator + if (needShowTopIndicator()) { + fillTopIndicatorDrawRect(); + canvas.drawRect(mTemp, mPaint); + } + // Draw bottom indicator + if (needShowBottomIndicator()) { + fillBottomIndicatorDrawRect(); + canvas.drawRect(mTemp, mPaint); + } + + canvas.restoreToCount(restoreCount); + } +} diff --git a/app/src/main/java/com/hippo/widget/NotifyingScrollView.java b/app/src/main/java/com/hippo/widget/NotifyingScrollView.java new file mode 100644 index 000000000..1e491151c --- /dev/null +++ b/app/src/main/java/com/hippo/widget/NotifyingScrollView.java @@ -0,0 +1,50 @@ +/* + * 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.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ScrollView; + +public class NotifyingScrollView extends ScrollView { + + private OnScrollChangeListener mOnScrollChangeListener; + + public NotifyingScrollView(Context context) { + super(context); + } + + public NotifyingScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NotifyingScrollView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public void setOnScrollChangeListener(OnScrollChangeListener listener) { + mOnScrollChangeListener = listener; + } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + + if (mOnScrollChangeListener != null) { + mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt); + } + } +} diff --git a/app/src/main/java/com/hippo/widget/OnScrollChangeListener.java b/app/src/main/java/com/hippo/widget/OnScrollChangeListener.java new file mode 100644 index 000000000..b1341b6ce --- /dev/null +++ b/app/src/main/java/com/hippo/widget/OnScrollChangeListener.java @@ -0,0 +1,35 @@ +/* + * 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.widget; + +import android.view.View; + +/** + * Interface definition for a callback to be invoked when the scroll + * position of a view changes. + */ +public interface OnScrollChangeListener { + /** + * Called when the scroll position of a view changes. + * + * @param v The view whose scroll position has changed. + * @param scrollX Current horizontal scroll origin. + * @param scrollY Current vertical scroll origin. + * @param oldScrollX Previous horizontal scroll origin. + * @param oldScrollY Previous vertical scroll origin. + */ + void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY); +} diff --git a/app/src/main/res/layout/simple_dialog.xml b/app/src/main/res/layout/simple_dialog.xml index 19288d477..076c735db 100644 --- a/app/src/main/res/layout/simple_dialog.xml +++ b/app/src/main/res/layout/simple_dialog.xml @@ -15,31 +15,49 @@ --> + android:layout_height="wrap_content" + android:paddingLeft="@dimen/simple_dialog_body_padding_left" + android:paddingRight="@dimen/simple_dialog_body_padding_right" + tools:ignore="RtlHardcoded"/> + android:layout_height="@dimen/simple_dialog_title_content_gap"/> - + android:layout_height="wrap_content"> + + + + @@ -49,8 +67,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:padding="8dp" - android:visibility="gone"> + android:padding="8dp"> #deffffff #61ffffff - - + #ff303030 #ffeeeeee #ffe1e1e0 @@ -81,4 +80,7 @@ #38000000 + + #20000000 + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 62b3a5c7b..8cc90ed74 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -15,8 +15,17 @@ --> + 16dp 320dp + 24dp + 24dp + 24dp + 18dp + 18dp + + + 1dp 8dp diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index ef42157f7..dfb9979e8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -83,18 +83,26 @@ @drawable/progress_large_material - - + +