Improve gallery
This commit is contained in:
1 parent
56c95740df
commit
9a18ad543a
37 files changed
+2281
-592
No files matched your search
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.drawable;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
|
||||
public class BatteryDrawable extends Drawable {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = BatteryDrawable.class.getSimpleName();
|
||||
|
||||
public static final int WARN_LIMIT = 15;
|
||||
|
||||
private int mColor = Color.WHITE;
|
||||
private int mWarningColor = Color.RED;
|
||||
private int mElect = -1;
|
||||
private final Paint mPaint;
|
||||
|
||||
private final Rect mTopRect;
|
||||
private final Rect mBottomRect;
|
||||
private final Rect mRightRect;
|
||||
private final Rect mHeadRect;
|
||||
private final Rect mElectRect;
|
||||
private int mStart;
|
||||
private int mStop;
|
||||
|
||||
public BatteryDrawable() {
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
|
||||
mTopRect = new Rect();
|
||||
mBottomRect = new Rect();
|
||||
mRightRect = new Rect();
|
||||
mHeadRect = new Rect();
|
||||
mElectRect = new Rect();
|
||||
updatePaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
int width = bounds.width();
|
||||
int height = bounds.height();
|
||||
int strokeWidth = (int) (Math.sqrt(width * width + height * height) * 0.06f);
|
||||
int turn1 = width * 6 / 7;
|
||||
int turn2 = height / 3;
|
||||
int secBottom = height - strokeWidth;
|
||||
mStart = strokeWidth;
|
||||
mStop = turn1 - strokeWidth;
|
||||
|
||||
mTopRect.set(0, 0, turn1, strokeWidth);
|
||||
mBottomRect.set(0, secBottom, turn1, height);
|
||||
mRightRect.set(turn1 - strokeWidth, strokeWidth, turn1, secBottom);
|
||||
mHeadRect.set(turn1, turn2, width, height - turn2);
|
||||
mElectRect.set(0, strokeWidth, mStop, secBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* How to draw:<br>
|
||||
* |------------------------------|<br>
|
||||
* |\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\|<br>
|
||||
* |------------------------------|---|<br>
|
||||
* |/////////////////| |//|\\\|<br>
|
||||
* |/////////////////| |//|\\\|<br>
|
||||
* |------------------------------|---|<br>
|
||||
* |\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\|<br>
|
||||
* |------------------------------|
|
||||
*/
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mElect == -1)
|
||||
return;
|
||||
|
||||
mElectRect.right = MathUtils.lerp(mStart, mStop, mElect / 100.0f);
|
||||
|
||||
canvas.drawRect(mTopRect, mPaint);
|
||||
canvas.drawRect(mBottomRect, mPaint);
|
||||
canvas.drawRect(mRightRect, mPaint);
|
||||
canvas.drawRect(mHeadRect, mPaint);
|
||||
canvas.drawRect(mElectRect, mPaint);
|
||||
}
|
||||
|
||||
private boolean isWarn() {
|
||||
return mElect <= WARN_LIMIT;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
if (mColor == color) {
|
||||
return;
|
||||
}
|
||||
|
||||
mColor = color;
|
||||
if (!isWarn()) {
|
||||
mPaint.setColor(mColor);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public void setWarningColor(int color) {
|
||||
if (mWarningColor == color) {
|
||||
return;
|
||||
}
|
||||
|
||||
mWarningColor = color;
|
||||
if (isWarn()) {
|
||||
mPaint.setColor(mWarningColor);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public void setElect(int elect) {
|
||||
if (mElect == elect) {
|
||||
return;
|
||||
}
|
||||
|
||||
mElect = elect;
|
||||
updatePaint();
|
||||
}
|
||||
|
||||
public void setElect(int elect, boolean warn) {
|
||||
if (mElect == elect) {
|
||||
return;
|
||||
}
|
||||
|
||||
mElect = elect;
|
||||
updatePaint(warn);
|
||||
}
|
||||
|
||||
private void updatePaint() {
|
||||
updatePaint(isWarn());
|
||||
}
|
||||
|
||||
private void updatePaint(boolean warn) {
|
||||
if (warn)
|
||||
mPaint.setColor(mWarningColor);
|
||||
else
|
||||
mPaint.setColor(mColor);
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
}
|
||||
@@ -119,6 +119,9 @@ public class Settings {
|
||||
return sEhConfig;
|
||||
}
|
||||
|
||||
/********************
|
||||
****** Eh
|
||||
********************/
|
||||
private static final String KEY_SHOW_JPN_TITLE = "show_jpn_title";
|
||||
private static final boolean DEFAULT_SHOW_JPN_TITLE = false;
|
||||
|
||||
@@ -126,6 +129,16 @@ public class Settings {
|
||||
return getBoolean(KEY_SHOW_JPN_TITLE, DEFAULT_SHOW_JPN_TITLE);
|
||||
}
|
||||
|
||||
/********************
|
||||
****** Read
|
||||
********************/
|
||||
private static final String KEY_VOLUME_PAGE = "volume_page";
|
||||
private static final boolean DEFAULT_VOLUME_PAGE = false;
|
||||
|
||||
public static boolean getVolumePage() {
|
||||
return getBoolean(KEY_VOLUME_PAGE, DEFAULT_VOLUME_PAGE);
|
||||
}
|
||||
|
||||
public static final String KEY_DOWNLOAD_SAVE_SCHEME = "image_scheme";
|
||||
public static final String KEY_DOWNLOAD_SAVE_AUTHORITY = "image_authority";
|
||||
public static final String KEY_DOWNLOAD_SAVE_PATH = "image_path";
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.support.annotation.Nullable;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.spider.SpiderQueen;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
|
||||
public class EhGalleryProvider extends GalleryProvider implements SpiderQueen.OnSpiderListener {
|
||||
|
||||
@@ -49,7 +50,15 @@ public class EhGalleryProvider extends GalleryProvider implements SpiderQueen.On
|
||||
|
||||
if (mSpiderQueen != null) {
|
||||
mSpiderQueen.removeOnSpiderListener(this);
|
||||
SpiderQueen.releaseSpiderQueen(mSpiderQueen, SpiderQueen.MODE_READ);
|
||||
final SpiderQueen spiderQueen = mSpiderQueen;
|
||||
mSpiderQueen = null;
|
||||
// Activity recreate may called
|
||||
SimpleHandler.getInstance().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
SpiderQueen.releaseSpiderQueen(spiderQueen, SpiderQueen.MODE_READ);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import android.support.annotation.UiThread;
|
||||
import com.hippo.gl.glrenderer.GLCanvas;
|
||||
import com.hippo.gl.view.GLRoot;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.yorozuya.ConcurrentPool;
|
||||
import com.hippo.yorozuya.OSUtils;
|
||||
import com.hippo.yorozuya.Pool;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -41,7 +41,7 @@ public abstract class GalleryProvider {
|
||||
".gif", // Graphics Interchange Format
|
||||
};
|
||||
|
||||
private final Pool<NotifyTask> mNotifyTaskPool = new Pool<>(5);
|
||||
private final ConcurrentPool<NotifyTask> mNotifyTaskPool = new ConcurrentPool<>(5);
|
||||
private volatile GalleryProviderListener mGalleryProviderListener;
|
||||
private volatile GLRoot mGLRoot;
|
||||
|
||||
@@ -130,8 +130,8 @@ public abstract class GalleryProvider {
|
||||
public static final int TYPE_SUCCEED = 2;
|
||||
public static final int TYPE_FAILED = 3;
|
||||
|
||||
private GalleryProviderListener mGalleryProviderListener;
|
||||
private Pool<NotifyTask> mPool;
|
||||
private final GalleryProviderListener mGalleryProviderListener;
|
||||
private final ConcurrentPool<NotifyTask> mPool;
|
||||
|
||||
@Type
|
||||
private int mType;
|
||||
@@ -140,7 +140,7 @@ public abstract class GalleryProvider {
|
||||
private Image mImage;
|
||||
private String mError;
|
||||
|
||||
public NotifyTask(GalleryProviderListener galleryProviderListener, Pool<NotifyTask> pool) {
|
||||
public NotifyTask(GalleryProviderListener galleryProviderListener, ConcurrentPool<NotifyTask> pool) {
|
||||
mGalleryProviderListener = galleryProviderListener;
|
||||
mPool = pool;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import com.hippo.yorozuya.LayoutUtils;
|
||||
|
||||
public class GalleryPageView extends GLFrameLayout {
|
||||
|
||||
public static final int INVALID_INDEX = -1;
|
||||
|
||||
private static final int INFO_INTERVAL = 24;
|
||||
public static final float PROGRESS_GONE = -1.0f;
|
||||
public static final float PROGRESS_INDETERMINATE = -2.0f;
|
||||
@@ -43,6 +45,8 @@ public class GalleryPageView extends GLFrameLayout {
|
||||
private GLTextureView mError;
|
||||
private GLProgressView mProgress;
|
||||
|
||||
private int mIndex = INVALID_INDEX;
|
||||
|
||||
public GalleryPageView(Context context, MovableTextTexture pageTextTexture,
|
||||
int progressColor, int progressSize) {
|
||||
// Add image
|
||||
@@ -87,6 +91,14 @@ public class GalleryPageView extends GLFrameLayout {
|
||||
mInfo.addComponent(mProgress, lp);
|
||||
}
|
||||
|
||||
int getIndex() {
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
void setIndex(int index) {
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
public void showImage() {
|
||||
mImage.setVisibility(VISIBLE);
|
||||
mInfo.setVisibility(GONE);
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
@@ -38,11 +37,13 @@ import com.hippo.gl.widget.GLEdgeView;
|
||||
import com.hippo.gl.widget.GLProgressView;
|
||||
import com.hippo.gl.widget.GLTextureView;
|
||||
import com.hippo.yorozuya.LayoutUtils;
|
||||
import com.hippo.yorozuya.Pool;
|
||||
import com.hippo.yorozuya.ResourcesUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Stack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
|
||||
@@ -60,7 +61,6 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
private @interface LayoutMode {}
|
||||
|
||||
public static final int BACKGROUND_COLOR = 0xff212121;
|
||||
private static final int INTERVAL_IN_DP = 24;
|
||||
private static final int PROGRESS_SIZE_IN_DP = 48;
|
||||
private static final int PAGE_MIN_HEIGHT_IN_DP = 256;
|
||||
|
||||
@@ -84,37 +84,55 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
private static final float[] RIGHT_AREA = {2.0f / 3.0f, 0.0f, 1.0f, 1f};
|
||||
private static final float[] CENTER_AREA = {1.0f / 3.0f, 2.0f / 5.0f, 2.0f / 3.0f, 3.0f / 5.0f};
|
||||
|
||||
private Context mContext;
|
||||
private MovableTextTexture mPageTextTexture;
|
||||
private GestureRecognizer mGestureRecognizer;
|
||||
private PageIterator mIterator;
|
||||
private static final int METHOD_ON_SINGLE_TAP_UP = 0;
|
||||
private static final int METHOD_ON_SINGLE_TAP_CONFIRMED = 1;
|
||||
private static final int METHOD_ON_DOUBLE_TAP = 2;
|
||||
private static final int METHOD_ON_DOUBLE_TAP_CONFIRMED = 3;
|
||||
private static final int METHOD_ON_SCROLL = 4;
|
||||
private static final int METHOD_ON_FLING = 5;
|
||||
private static final int METHOD_ON_SCALE_BEGIN = 6;
|
||||
private static final int METHOD_ON_SCALE = 7;
|
||||
private static final int METHOD_ON_SCALE_END = 8;
|
||||
private static final int METHOD_ON_DOWN = 9;
|
||||
private static final int METHOD_ON_UP = 10;
|
||||
private static final int METHOD_ON_POINTER_DOWN = 11;
|
||||
private static final int METHOD_ON_POINTER_UP = 12;
|
||||
private static final int METHOD_SET_LAYOUT_MODE = 13;
|
||||
|
||||
private final Context mContext;
|
||||
private final MovableTextTexture mPageTextTexture;
|
||||
private final GestureRecognizer mGestureRecognizer;
|
||||
private Adapter mAdapter;
|
||||
|
||||
private PagerLayoutManager mPagerLayoutManager;
|
||||
private ScrollLayoutManager mScrollLayoutManager;
|
||||
private LayoutManager mLayoutManager;
|
||||
|
||||
private Recycler mRecycler;
|
||||
private GLEdgeView mEdgeView;
|
||||
private final Pool<GalleryPageView> mGalleryPageViewPool = new Pool<>(5);
|
||||
private final GLEdgeView mEdgeView;
|
||||
private GLProgressView mProgressCache;
|
||||
private GLTextureView mErrorViewCache;
|
||||
|
||||
private int mProgressColor;
|
||||
private int mProgressSize;
|
||||
private float mErrorSize;
|
||||
private int mErrorColor;
|
||||
private int mPageMinHeight;
|
||||
private int mInterval;
|
||||
private final int mProgressColor;
|
||||
private final int mProgressSize;
|
||||
private final float mErrorSize;
|
||||
private final int mErrorColor;
|
||||
private final int mPageMinHeight;
|
||||
|
||||
private boolean mEnableRequestFill = true;
|
||||
private boolean mRequestFill = false;
|
||||
|
||||
private boolean mScale = false;
|
||||
private boolean mScroll = false;
|
||||
private boolean mFirstScroll = false;
|
||||
private boolean mTouched = false;
|
||||
|
||||
private Rect mLeftArea = new Rect();
|
||||
private Rect mRightArea = new Rect();
|
||||
private Rect mCenterArea = new Rect();
|
||||
private final Rect mLeftArea = new Rect();
|
||||
private final Rect mRightArea = new Rect();
|
||||
private final Rect mCenterArea = new Rect();
|
||||
|
||||
private final String mDefaultErrorStr;
|
||||
private final String mEmptyStr;
|
||||
|
||||
@LayoutMode
|
||||
private int mLayoutMode = LAYOUT_MODE_RIGHT_TO_LEFT;
|
||||
@@ -124,21 +142,23 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
@StartPosition
|
||||
private int mStartPosition = START_POSITION_TOP_LEFT;
|
||||
|
||||
private boolean mRequestFill = false;
|
||||
private final ActionListener mListener;
|
||||
|
||||
private ActionListener mListener;
|
||||
private final List<Integer> mMethodList = new ArrayList<>(5);
|
||||
private final List<Object[]> mArgsList = new ArrayList<>(5);
|
||||
private final List<Integer> mMethodListTemp = new ArrayList<>(5);
|
||||
private final List<Object[]> mArgsListTemp = new ArrayList<>(5);
|
||||
|
||||
public GalleryView(Context context, PageIterator iterator, MovableTextTexture pageTextTexture,
|
||||
ActionListener listener, @LayoutMode int layoutMode) {
|
||||
public GalleryView(@NonNull Context context, @NonNull Adapter adapter,
|
||||
MovableTextTexture pageTextTexture, ActionListener listener, @LayoutMode int layoutMode) {
|
||||
mContext = context;
|
||||
mIterator = iterator;
|
||||
mAdapter = adapter;
|
||||
mPageTextTexture = pageTextTexture;
|
||||
mListener = listener;
|
||||
mEdgeView = new GLEdgeView(context);
|
||||
mGestureRecognizer = new GestureRecognizer(context, this);
|
||||
mRecycler = new Recycler();
|
||||
|
||||
iterator.setGalleryView(this);
|
||||
adapter.setGalleryView(this);
|
||||
|
||||
mLayoutMode = layoutMode;
|
||||
mProgressColor = ResourcesUtils.getAttrColor(context, R.attr.colorPrimary);
|
||||
@@ -146,7 +166,9 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
mErrorSize = context.getResources().getDimension(R.dimen.text_large);
|
||||
mErrorColor = context.getResources().getColor(R.color.red_500);
|
||||
mPageMinHeight = LayoutUtils.dp2pix(context, PAGE_MIN_HEIGHT_IN_DP);
|
||||
mInterval = LayoutUtils.dp2pix(context, INTERVAL_IN_DP);
|
||||
|
||||
mDefaultErrorStr = context.getResources().getString(R.string.error_unknown);
|
||||
mEmptyStr = context.getResources().getString(R.string.error_empty);
|
||||
|
||||
setBackgroundColor(BACKGROUND_COLOR);
|
||||
}
|
||||
@@ -159,7 +181,7 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
|
||||
private void ensureScrollLayoutManager() {
|
||||
if (mScrollLayoutManager == null) {
|
||||
mScrollLayoutManager = new ScrollLayoutManager(mContext, this, mInterval);
|
||||
mScrollLayoutManager = new ScrollLayoutManager(mContext, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,24 +194,26 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
case LAYOUT_MODE_LEFT_TO_RIGHT:
|
||||
ensurePagerLayoutManager();
|
||||
mPagerLayoutManager.setMode(PagerLayoutManager.MODE_LEFT_TO_RIGHT);
|
||||
mPagerLayoutManager.onAttach(mIterator);
|
||||
mIterator = null;
|
||||
mPagerLayoutManager.onAttach(mAdapter);
|
||||
mAdapter = null;
|
||||
mLayoutManager = mPagerLayoutManager;
|
||||
break;
|
||||
case LAYOUT_MODE_RIGHT_TO_LEFT:
|
||||
ensurePagerLayoutManager();
|
||||
mPagerLayoutManager.setMode(PagerLayoutManager.MODE_RIGHT_TO_LEFT);
|
||||
mPagerLayoutManager.onAttach(mIterator);
|
||||
mIterator = null;
|
||||
mPagerLayoutManager.onAttach(mAdapter);
|
||||
mAdapter = null;
|
||||
mLayoutManager = mPagerLayoutManager;
|
||||
break;
|
||||
case LAYOUT_MODE_TOP_TO_BOTTOM:
|
||||
ensureScrollLayoutManager();
|
||||
mScrollLayoutManager.onAttach(mIterator);
|
||||
mIterator = null;
|
||||
mScrollLayoutManager.onAttach(mAdapter);
|
||||
mAdapter = null;
|
||||
mLayoutManager = mScrollLayoutManager;
|
||||
break;
|
||||
}
|
||||
|
||||
requestFill();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,7 +221,7 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
super.onDetachFromRoot();
|
||||
mEdgeView.onDetachFromRoot();
|
||||
|
||||
mIterator = mLayoutManager.onDetach();
|
||||
mAdapter = mLayoutManager.onDetach();
|
||||
mLayoutManager = null;
|
||||
}
|
||||
|
||||
@@ -225,13 +249,215 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
return mEdgeView;
|
||||
}
|
||||
|
||||
public boolean isFirstScroll() {
|
||||
String getDefaultErrorStr() {
|
||||
return mDefaultErrorStr;
|
||||
}
|
||||
|
||||
String getEmptyStr() {
|
||||
return mEmptyStr;
|
||||
}
|
||||
|
||||
boolean isFirstScroll() {
|
||||
boolean firstScroll = mFirstScroll;
|
||||
mFirstScroll = false;
|
||||
return firstScroll;
|
||||
}
|
||||
|
||||
// Make sure method run in render thread to ensure thread safe
|
||||
private void postMethod(int method, Object... args) {
|
||||
synchronized (this) {
|
||||
mMethodList.add(method);
|
||||
mArgsList.add(args);
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setLayoutMode(@LayoutMode int layoutMode) {
|
||||
postMethod(METHOD_SET_LAYOUT_MODE, layoutMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapUp(float x, float y) {
|
||||
postMethod(METHOD_ON_SINGLE_TAP_UP, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(float x, float y) {
|
||||
postMethod(METHOD_ON_SINGLE_TAP_CONFIRMED, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(float x, float y) {
|
||||
postMethod(METHOD_ON_DOUBLE_TAP, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTapConfirmed(float x, float y) {
|
||||
postMethod(METHOD_ON_DOUBLE_TAP_CONFIRMED, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(float dx, float dy, float totalX, float totalY, float x, float y) {
|
||||
postMethod(METHOD_ON_SCROLL, dx, dy, totalX, totalY, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
postMethod(METHOD_ON_FLING, velocityX, velocityY);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(float focusX, float focusY) {
|
||||
postMethod(METHOD_ON_SCALE_BEGIN, focusX, focusY);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(float focusX, float focusY, float scale) {
|
||||
postMethod(METHOD_ON_SCALE, focusX, focusY, scale);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd() {
|
||||
postMethod(METHOD_ON_SCALE_END);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDown(float x, float y) {
|
||||
postMethod(METHOD_ON_DOWN, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUp() {
|
||||
postMethod(METHOD_ON_UP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerDown(float x, float y) {
|
||||
postMethod(METHOD_ON_POINTER_DOWN, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerUp() {
|
||||
postMethod(METHOD_ON_POINTER_UP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changeSize, int left, int top, int right, int bottom) {
|
||||
mEdgeView.layout(left, top, right, bottom);
|
||||
|
||||
fill();
|
||||
|
||||
if (changeSize) {
|
||||
int width = right - left;
|
||||
int height = bottom - top;
|
||||
mLeftArea.set((int) (LEFT_AREA[0] * width), (int) (LEFT_AREA[1] * height),
|
||||
(int) (LEFT_AREA[2] * width), (int) (LEFT_AREA[3] * height));
|
||||
mRightArea.set((int) (RIGHT_AREA[0] * width), (int) (RIGHT_AREA[1] * height),
|
||||
(int) (RIGHT_AREA[2] * width), (int) (RIGHT_AREA[3] * height));
|
||||
mCenterArea.set((int) (CENTER_AREA[0] * width), (int) (CENTER_AREA[1] * height),
|
||||
(int) (CENTER_AREA[2] * width), (int) (CENTER_AREA[3] * height));
|
||||
}
|
||||
}
|
||||
|
||||
@RenderThread
|
||||
public void onDataChanged() {
|
||||
GalleryUtils.assertInRenderThread();
|
||||
|
||||
if (mLayoutManager != null){
|
||||
mLayoutManager.onDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void onSingleTapUpInternal(float x, float y) {
|
||||
}
|
||||
|
||||
private void onSingleTapConfirmedInternal(float x, float y) {
|
||||
}
|
||||
|
||||
private void onDoubleTapInternal(float x, float y) {
|
||||
}
|
||||
|
||||
private void onDoubleTapConfirmedInternal(float x, float y) {
|
||||
if (mScale) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onDoubleTapConfirmed(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private void onScrollInternal(float dx, float dy, float totalX, float totalY, float x, float y) {
|
||||
if (mScale) {
|
||||
return;
|
||||
}
|
||||
mScroll = true;
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onScroll(dx, dy, totalX, totalY, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private void onFlingInternal(float velocityX, float velocityY) {
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onFling(velocityX, velocityY);
|
||||
}
|
||||
}
|
||||
|
||||
private void onScaleBeginInternal(float focusX, float focusY) {
|
||||
onScaleInternal(focusX, focusY, 1.0f);
|
||||
}
|
||||
|
||||
private void onScaleInternal(float focusX, float focusY, float scale) {
|
||||
if (mScroll || (mLayoutManager != null && !mLayoutManager.canScale())) {
|
||||
return;
|
||||
}
|
||||
mScale = true;
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onScale(focusX, focusY, scale);
|
||||
}
|
||||
}
|
||||
|
||||
private void onScaleEndInternal() {
|
||||
}
|
||||
|
||||
private void onDownInternal(float x, float y) {
|
||||
mTouched = true;
|
||||
mScale = false;
|
||||
mScroll = false;
|
||||
mFirstScroll = true;
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onDown();
|
||||
}
|
||||
}
|
||||
|
||||
private void onUpInternal() {
|
||||
mTouched = false;
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onUp();
|
||||
}
|
||||
}
|
||||
|
||||
private void onPointerDownInternal(float x, float y) {
|
||||
if (!mScroll && (mLayoutManager != null && mLayoutManager.canScale())) {
|
||||
mScale = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void onPointerUpInternal() {
|
||||
}
|
||||
|
||||
private void setLayoutModeInternal(int layoutMode) {
|
||||
if (mLayoutMode == layoutMode) {
|
||||
return;
|
||||
}
|
||||
@@ -270,169 +496,132 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
mLayoutManager = mScrollLayoutManager;
|
||||
break;
|
||||
}
|
||||
|
||||
requestFill();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapUp(float x, float y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(float x, float y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(float x, float y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTapConfirmed(float x, float y) {
|
||||
if (mScale) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onDoubleTapConfirmed(x, y);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(float dx, float dy, float totalX, float totalY, float x, float y) {
|
||||
if (mScale) {
|
||||
return false;
|
||||
}
|
||||
mScroll = true;
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onScroll(dx, dy, totalX, totalY, x, y);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onFling(e1, e2, velocityX, velocityY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(float focusX, float focusY) {
|
||||
return onScale(focusX, focusY, 1.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(float focusX, float focusY, float scale) {
|
||||
if (mScroll || (mLayoutManager != null && !mLayoutManager.canScale())) {
|
||||
return false;
|
||||
}
|
||||
mScale = true;
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onScale(focusX, focusY, scale);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDown(float x, float y) {
|
||||
mTouched = true;
|
||||
mScale = false;
|
||||
mScroll = false;
|
||||
mFirstScroll = true;
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUp() {
|
||||
mTouched = false;
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onUp();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerDown(float x, float y) {
|
||||
if (!mScroll && (mLayoutManager != null && mLayoutManager.canScale())) {
|
||||
mScale = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerUp() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changeSize, int left, int top, int right, int bottom) {
|
||||
mEdgeView.layout(left, top, right, bottom);
|
||||
|
||||
@RenderThread
|
||||
void forceFill() {
|
||||
mRequestFill = true;
|
||||
fill();
|
||||
|
||||
if (changeSize) {
|
||||
int width = right - left;
|
||||
int height = bottom - top;
|
||||
mLeftArea.set((int) (LEFT_AREA[0] * width), (int) (LEFT_AREA[1] * height),
|
||||
(int) (LEFT_AREA[2] * width), (int) (LEFT_AREA[3] * height));
|
||||
mRightArea.set((int) (RIGHT_AREA[0] * width), (int) (RIGHT_AREA[1] * height),
|
||||
(int) (RIGHT_AREA[2] * width), (int) (RIGHT_AREA[3] * height));
|
||||
mCenterArea.set((int) (CENTER_AREA[0] * width), (int) (CENTER_AREA[1] * height),
|
||||
(int) (CENTER_AREA[2] * width), (int) (CENTER_AREA[3] * height));
|
||||
}
|
||||
}
|
||||
|
||||
@RenderThread
|
||||
private void fill() {
|
||||
// Must be in render thread
|
||||
GalleryUtils.assertInRenderThread();
|
||||
|
||||
if (!mRequestFill) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable request layout
|
||||
mEnableRequestFill = false;
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onFill();
|
||||
}
|
||||
mEnableRequestFill = true;
|
||||
mRequestFill = false;
|
||||
}
|
||||
|
||||
private void dispatchMethod() {
|
||||
List<Integer> methodListTemp = mMethodListTemp;
|
||||
List<Object[]> argsListTemp = mArgsListTemp;
|
||||
|
||||
synchronized (this) {
|
||||
if (mMethodList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
methodListTemp.addAll(mMethodList);
|
||||
argsListTemp.addAll(mArgsList);
|
||||
mMethodList.clear();
|
||||
mArgsList.clear();
|
||||
}
|
||||
|
||||
for (int i = 0, n = methodListTemp.size(); i < n; i++) {
|
||||
int method = methodListTemp.get(i);
|
||||
Object[] args = argsListTemp.get(i);
|
||||
|
||||
switch (method) {
|
||||
case METHOD_ON_SINGLE_TAP_UP:
|
||||
onSingleTapUpInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_SINGLE_TAP_CONFIRMED:
|
||||
onSingleTapConfirmedInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_DOUBLE_TAP:
|
||||
onDoubleTapInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_DOUBLE_TAP_CONFIRMED:
|
||||
onDoubleTapConfirmedInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_SCROLL:
|
||||
onScrollInternal((Float) args[0], (Float) args[1], (Float) args[2],
|
||||
(Float) args[3], (Float) args[4], (Float) args[5]);
|
||||
break;
|
||||
case METHOD_ON_FLING:
|
||||
onFlingInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_SCALE_BEGIN:
|
||||
onScaleBeginInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_SCALE:
|
||||
onScaleInternal((Float) args[0], (Float) args[1], (Float) args[2]);
|
||||
break;
|
||||
case METHOD_ON_SCALE_END:
|
||||
onScaleEndInternal();
|
||||
break;
|
||||
case METHOD_ON_DOWN:
|
||||
onDownInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_UP:
|
||||
onUpInternal();
|
||||
break;
|
||||
case METHOD_ON_POINTER_DOWN:
|
||||
onPointerDownInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_POINTER_UP:
|
||||
onPointerUpInternal();
|
||||
break;
|
||||
case METHOD_SET_LAYOUT_MODE:
|
||||
setLayoutModeInternal((Integer) args[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
methodListTemp.clear();
|
||||
argsListTemp.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GLCanvas canvas) {
|
||||
// Dispatch method
|
||||
dispatchMethod();
|
||||
|
||||
long time = AnimationTime.get();
|
||||
if (mLayoutManager != null && mLayoutManager.onUpdateAnimation(time)) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// mSmoothScroller may do fill too, so check fill request after scroll animator
|
||||
if (mRequestFill) {
|
||||
mRequestFill = false;
|
||||
fill();
|
||||
}
|
||||
fill();
|
||||
|
||||
super.render(canvas);
|
||||
mEdgeView.render(canvas);
|
||||
}
|
||||
|
||||
public GalleryPageView findPageById(int id) {
|
||||
@RenderThread
|
||||
public GalleryPageView findPageByIndex(int id) {
|
||||
GalleryUtils.assertInRenderThread();
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
return mLayoutManager.findPageById(id);
|
||||
return mLayoutManager.findPageByIndex(id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public GalleryPageView obtainPage() {
|
||||
GalleryPageView page = mRecycler.obtain();
|
||||
GalleryPageView obtainPage() {
|
||||
GalleryPageView page = mGalleryPageViewPool.pop();
|
||||
if (page == null) {
|
||||
page = new GalleryPageView(mContext, mPageTextTexture, mProgressColor, mProgressSize);
|
||||
page.setMinimumHeight(mPageMinHeight);
|
||||
@@ -440,14 +629,14 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void releasePage(GalleryPageView page) {
|
||||
mRecycler.release(page);
|
||||
void releasePage(GalleryPageView page) {
|
||||
mGalleryPageViewPool.push(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indeterminate GLProgressView
|
||||
*/
|
||||
public GLProgressView obtainProgress() {
|
||||
GLProgressView obtainProgress() {
|
||||
GLProgressView progress;
|
||||
if (mProgressCache != null) {
|
||||
progress = mProgressCache;
|
||||
@@ -466,11 +655,11 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
/**
|
||||
* @param progress Indeterminate GLProgressView
|
||||
*/
|
||||
public void releaseProgress(GLProgressView progress) {
|
||||
void releaseProgress(GLProgressView progress) {
|
||||
mProgressCache = progress;
|
||||
}
|
||||
|
||||
public GLTextureView obtainErrorView() {
|
||||
GLTextureView obtainErrorView() {
|
||||
GLTextureView errorView;
|
||||
if (mErrorViewCache != null) {
|
||||
errorView = mErrorViewCache;
|
||||
@@ -481,7 +670,7 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
return errorView;
|
||||
}
|
||||
|
||||
public void unbindErrorView(GLTextureView errorView) {
|
||||
void unbindErrorView(GLTextureView errorView) {
|
||||
Texture texture = errorView.getTexture();
|
||||
if (texture != null) {
|
||||
errorView.setTexture(null);
|
||||
@@ -491,28 +680,19 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
}
|
||||
}
|
||||
|
||||
public void bindErrorView(GLTextureView errorView, String error) {
|
||||
void bindErrorView(GLTextureView errorView, String error) {
|
||||
unbindErrorView(errorView);
|
||||
|
||||
Texture texture = StringTexture.newInstance(error, mErrorSize, mErrorColor);
|
||||
errorView.setTexture(texture);
|
||||
}
|
||||
|
||||
public void releaseErrorView(GLTextureView errorView) {
|
||||
void releaseErrorView(GLTextureView errorView) {
|
||||
unbindErrorView(errorView);
|
||||
mErrorViewCache = errorView;
|
||||
}
|
||||
|
||||
@RenderThread
|
||||
public void onDataChanged() {
|
||||
GalleryUtils.assertInRenderThread();
|
||||
|
||||
if (mLayoutManager != null){
|
||||
mLayoutManager.onDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class PageIterator {
|
||||
public static abstract class Adapter {
|
||||
|
||||
protected GalleryView mGalleryView;
|
||||
|
||||
@@ -520,41 +700,26 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
mGalleryView = galleryView;
|
||||
}
|
||||
|
||||
public abstract void mark();
|
||||
public void bind(GalleryPageView view, int index) {
|
||||
onBind(view, index);
|
||||
view.setIndex(index);
|
||||
}
|
||||
|
||||
public abstract void reset();
|
||||
public void unbind(GalleryPageView view) {
|
||||
onUnbind(view);
|
||||
view.setIndex(GalleryPageView.INVALID_INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True for waiting now, layout manager
|
||||
* should show a progress bar or something like it
|
||||
*/
|
||||
public abstract boolean isWaiting();
|
||||
public abstract void onBind(GalleryPageView view, int index);
|
||||
|
||||
public abstract void onUnbind(GalleryPageView view);
|
||||
|
||||
/**
|
||||
* @return Null for no error
|
||||
*/
|
||||
public abstract String getError();
|
||||
|
||||
public abstract boolean hasNext();
|
||||
|
||||
public abstract boolean hasPrevious();
|
||||
|
||||
public abstract void next();
|
||||
|
||||
public abstract void previous();
|
||||
|
||||
public void bind(GalleryPageView view) {
|
||||
view.setId(onBind(view));
|
||||
}
|
||||
|
||||
public void unbind(GalleryPageView view) {
|
||||
onUnbind(view);
|
||||
view.setId(NO_ID);
|
||||
}
|
||||
|
||||
public abstract int onBind(GalleryPageView view);
|
||||
|
||||
public abstract void onUnbind(GalleryPageView view);
|
||||
public abstract int size();
|
||||
}
|
||||
|
||||
public static abstract class LayoutManager {
|
||||
@@ -565,9 +730,9 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
mGalleryView = galleryView;
|
||||
}
|
||||
|
||||
public abstract void onAttach(PageIterator iterator);
|
||||
public abstract void onAttach(Adapter iterator);
|
||||
|
||||
public abstract PageIterator onDetach();
|
||||
public abstract Adapter onDetach();
|
||||
|
||||
public abstract void onFill();
|
||||
|
||||
@@ -579,7 +744,7 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
|
||||
public abstract void onScroll(float dx, float dy, float totalX, float totalY, float x, float y);
|
||||
|
||||
public abstract void onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
|
||||
public abstract void onFling(float velocityX, float velocityY);
|
||||
|
||||
public abstract boolean canScale();
|
||||
|
||||
@@ -589,7 +754,12 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
|
||||
public abstract void onDataChanged();
|
||||
|
||||
public abstract GalleryPageView findPageById(int id);
|
||||
public abstract GalleryPageView findPageByIndex(int index);
|
||||
|
||||
/**
|
||||
* @return {@link GalleryPageView#INVALID_INDEX} for error
|
||||
*/
|
||||
public abstract int getCurrentIndex();
|
||||
|
||||
protected void placeCenter(GLView view) {
|
||||
int spec = GLView.MeasureSpec.makeMeasureSpec(GLView.LayoutParams.WRAP_CONTENT,
|
||||
@@ -603,36 +773,6 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
}
|
||||
}
|
||||
|
||||
private static class Recycler {
|
||||
|
||||
private static final int MAX_SIZE = 3;
|
||||
|
||||
private int mSize = 0;
|
||||
|
||||
private Stack<GalleryPageView> mStack = new Stack<>();
|
||||
|
||||
@Nullable
|
||||
private GalleryPageView obtain() {
|
||||
if (mSize != 0) {
|
||||
mSize--;
|
||||
return mStack.pop();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void release(@Nullable GalleryPageView page) {
|
||||
if (page == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSize < MAX_SIZE) {
|
||||
mSize++;
|
||||
mStack.push(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface ActionListener {
|
||||
|
||||
void onTapCenter();
|
||||
|
||||
@@ -19,10 +19,11 @@ package com.hippo.ehviewer.gallery.gl;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.MotionEvent;
|
||||
import android.util.Log;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.hippo.anani.AnimationUtils;
|
||||
import com.hippo.ehviewer.gallery.GalleryProvider;
|
||||
import com.hippo.gl.anim.Animation;
|
||||
import com.hippo.gl.view.GLView;
|
||||
import com.hippo.gl.widget.GLEdgeView;
|
||||
@@ -35,9 +36,10 @@ import com.hippo.yorozuya.MathUtils;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
// TODO Not safe ! Ensure change component in render thread
|
||||
public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
private static final String TAG = PagerLayoutManager.class.getSimpleName();
|
||||
|
||||
@IntDef({MODE_LEFT_TO_RIGHT, MODE_RIGHT_TO_LEFT})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
private @interface Mode {}
|
||||
@@ -55,7 +57,7 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
};
|
||||
|
||||
private GalleryView.PageIterator mIterator;
|
||||
private GalleryView.Adapter mAdapter;
|
||||
|
||||
private GLProgressView mProgress;
|
||||
private String mErrorStr;
|
||||
@@ -71,19 +73,22 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
private int mDeltaY;
|
||||
private boolean mCanScrollBetweenPages = false;
|
||||
|
||||
private int mInterval;
|
||||
private final int mInterval;
|
||||
|
||||
private int[] mScrollRemain = new int[2];
|
||||
private float[] mScaleDefault = new float[3];
|
||||
private final int[] mScrollRemain = new int[2];
|
||||
private final float[] mScaleDefault = new float[3];
|
||||
|
||||
private PageFling mPageFling;
|
||||
private SmoothScroller mSmoothScroller;
|
||||
private SmoothScaler mSmoothScaler;
|
||||
private final PageFling mPageFling;
|
||||
private final SmoothScroller mSmoothScroller;
|
||||
private final SmoothScaler mSmoothScaler;
|
||||
|
||||
// Current index
|
||||
private int mIndex;
|
||||
|
||||
public PagerLayoutManager(Context context, @NonNull GalleryView galleryView) {
|
||||
super(galleryView);
|
||||
mInterval = LayoutUtils.dp2pix(context, INTERVAL);
|
||||
|
||||
mInterval = LayoutUtils.dp2pix(context, INTERVAL);
|
||||
mPageFling = new PageFling(context);
|
||||
mSmoothScroller = new SmoothScroller();
|
||||
mSmoothScaler = new SmoothScaler();
|
||||
@@ -108,7 +113,7 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
mMode = mode;
|
||||
if (mIterator != null) {
|
||||
if (mAdapter != null) {
|
||||
// It is attached, refill
|
||||
// Cancel all animations
|
||||
cancelAllAnimations();
|
||||
@@ -124,10 +129,10 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(GalleryView.PageIterator iterator) {
|
||||
AssertUtils.assertEquals("The PagerLayoutManager is attached", mIterator, null);
|
||||
AssertUtils.assertNotEquals("The iterator is null", iterator, null);
|
||||
mIterator = iterator;
|
||||
public void onAttach(GalleryView.Adapter adapter) {
|
||||
AssertUtils.assertEquals("The PagerLayoutManager is attached", mAdapter, null);
|
||||
AssertUtils.assertNotEquals("The adapter is null", adapter, null);
|
||||
mAdapter = adapter;
|
||||
// Reset parameters
|
||||
resetParameters();
|
||||
}
|
||||
@@ -151,7 +156,7 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
private void removePage(@NonNull GalleryPageView page) {
|
||||
mGalleryView.removeComponent(page);
|
||||
mIterator.unbind(page);
|
||||
mAdapter.unbind(page);
|
||||
mGalleryView.releasePage(page);
|
||||
}
|
||||
|
||||
@@ -172,8 +177,8 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GalleryView.PageIterator onDetach() {
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", mIterator, null);
|
||||
public GalleryView.Adapter onDetach() {
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", mAdapter, null);
|
||||
|
||||
// Cancel all animations
|
||||
cancelAllAnimations();
|
||||
@@ -184,10 +189,10 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
removeAllPages();
|
||||
|
||||
// Clear iterator
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
mIterator = null;
|
||||
GalleryView.Adapter adapter = mAdapter;
|
||||
mAdapter = null;
|
||||
|
||||
return iterator;
|
||||
return adapter;
|
||||
}
|
||||
|
||||
private GalleryPageView getLeftPage() {
|
||||
@@ -200,18 +205,6 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void setLeftPage(GalleryPageView page) {
|
||||
switch (mMode) {
|
||||
case MODE_LEFT_TO_RIGHT:
|
||||
mPrevious = page;
|
||||
break;
|
||||
default:
|
||||
case MODE_RIGHT_TO_LEFT:
|
||||
mNext = page;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private GalleryPageView getRightPage() {
|
||||
switch (mMode) {
|
||||
case MODE_LEFT_TO_RIGHT:
|
||||
@@ -222,29 +215,38 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void setRightPage(GalleryPageView page) {
|
||||
switch (mMode) {
|
||||
case MODE_LEFT_TO_RIGHT:
|
||||
mNext = page;
|
||||
break;
|
||||
default:
|
||||
case MODE_RIGHT_TO_LEFT:
|
||||
mPrevious = page;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFill() {
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
GalleryView.Adapter adapter = mAdapter;
|
||||
GalleryView galleryView = mGalleryView;
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", iterator, null);
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", adapter, null);
|
||||
|
||||
int width = galleryView.getWidth();
|
||||
int height = galleryView.getHeight();
|
||||
String errorStr = iterator.getError();
|
||||
int size = adapter.size();
|
||||
String errorStr = adapter.getError();
|
||||
|
||||
if (size == GalleryProvider.STATE_WAIT) { // Wait here, show progress bar
|
||||
// Remove error view and all pages
|
||||
removeErrorView();
|
||||
removeAllPages();
|
||||
|
||||
// Ensure progress
|
||||
if (mProgress == null) {
|
||||
mProgress = galleryView.obtainProgress();
|
||||
galleryView.addComponent(mProgress);
|
||||
}
|
||||
|
||||
// Place progress center
|
||||
placeCenter(mProgress);
|
||||
} else if (size <= GalleryProvider.STATE_ERROR || size == 0) { // Get error or empty, show error text
|
||||
// Ensure error is not null
|
||||
if (0 == size) {
|
||||
errorStr = galleryView.getEmptyStr();
|
||||
} else if (null == errorStr) {
|
||||
errorStr = galleryView.getDefaultErrorStr();
|
||||
}
|
||||
|
||||
if (errorStr != null) {
|
||||
// Remove progress and all pages
|
||||
removeProgress();
|
||||
removeAllPages();
|
||||
@@ -263,61 +265,66 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
// Place error view center
|
||||
placeCenter(mErrorView);
|
||||
} else if (iterator.isWaiting()) {
|
||||
// Remove error view and all pages
|
||||
removeErrorView();
|
||||
removeAllPages();
|
||||
|
||||
// Ensure progress
|
||||
if (mProgress == null) {
|
||||
mProgress = galleryView.obtainProgress();
|
||||
galleryView.addComponent(mProgress);
|
||||
}
|
||||
|
||||
// Place progress center
|
||||
placeCenter(mProgress);
|
||||
} else {
|
||||
// Remove progress and error view
|
||||
removeProgress();
|
||||
removeErrorView();
|
||||
|
||||
// Ensure index in range
|
||||
int index = mIndex;
|
||||
if (index < 0) {
|
||||
index = 0;
|
||||
mIndex = index;
|
||||
removeAllPages();
|
||||
Log.e(TAG, "index < 0, index = " + index);
|
||||
} else if (index >= size) {
|
||||
index = size - 1;
|
||||
mIndex = index;
|
||||
removeAllPages();
|
||||
Log.e(TAG, "index >= size, index = " + index + ", size = " + size);
|
||||
}
|
||||
|
||||
// Ensure pages
|
||||
if (mCurrent == null) {
|
||||
mCurrent = galleryView.obtainPage();
|
||||
iterator.bind(mCurrent);
|
||||
adapter.bind(mCurrent, index);
|
||||
galleryView.addComponent(mCurrent);
|
||||
}
|
||||
if (mPrevious == null && iterator.hasPrevious()) {
|
||||
iterator.mark();
|
||||
iterator.previous();
|
||||
if (mPrevious == null && index > 0) {
|
||||
mPrevious = galleryView.obtainPage();
|
||||
iterator.bind(mPrevious);
|
||||
adapter.bind(mPrevious, index - 1);
|
||||
galleryView.addComponent(mPrevious);
|
||||
iterator.reset();
|
||||
} else if (mPrevious != null && index == 0) {
|
||||
removePage(mPrevious);
|
||||
}
|
||||
if (mNext == null && iterator.hasNext()) {
|
||||
iterator.mark();
|
||||
iterator.next();
|
||||
if (mNext == null && index < size - 1) {
|
||||
mNext = galleryView.obtainPage();
|
||||
iterator.bind(mNext);
|
||||
adapter.bind(mNext, index + 1);
|
||||
galleryView.addComponent(mNext);
|
||||
iterator.reset();
|
||||
} else if (mNext != null && index == size - 1) {
|
||||
removePage(mNext);
|
||||
}
|
||||
|
||||
GalleryPageView leftPage = getLeftPage();
|
||||
GalleryPageView rightPage = getRightPage();
|
||||
|
||||
// Fix offset
|
||||
final int min = rightPage == null ? 0 : -width - mInterval + 1;
|
||||
final int max = leftPage == null ? 0 : width + mInterval - 1;
|
||||
mOffset = MathUtils.clamp(mOffset, min, max);
|
||||
|
||||
// Measure and layout pages
|
||||
int offset = mOffset;
|
||||
int widthSpec = GLView.MeasureSpec.makeMeasureSpec(width, GLView.MeasureSpec.EXACTLY);
|
||||
int heightSpec = GLView.MeasureSpec.makeMeasureSpec(height, GLView.MeasureSpec.EXACTLY);
|
||||
final int offset = mOffset;
|
||||
final int widthSpec = GLView.MeasureSpec.makeMeasureSpec(width, GLView.MeasureSpec.EXACTLY);
|
||||
final int heightSpec = GLView.MeasureSpec.makeMeasureSpec(height, GLView.MeasureSpec.EXACTLY);
|
||||
if (mCurrent != null) {
|
||||
mCurrent.measure(widthSpec, heightSpec);
|
||||
mCurrent.layout(offset, 0, width + offset, height);
|
||||
}
|
||||
GalleryPageView leftPage = getLeftPage();
|
||||
if (leftPage != null) {
|
||||
leftPage.measure(widthSpec, heightSpec);
|
||||
leftPage.layout(-mInterval - width + offset, 0, -mInterval + offset, height);
|
||||
}
|
||||
GalleryPageView rightPage = getRightPage();
|
||||
if (rightPage != null) {
|
||||
rightPage.measure(widthSpec, heightSpec);
|
||||
rightPage.layout(width + mInterval + offset, 0, width + mInterval + width + offset, height);
|
||||
@@ -381,11 +388,10 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
private void pagePrevious() {
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
if (!iterator.hasPrevious()) {
|
||||
if (mIndex <= 0) {
|
||||
return;
|
||||
}
|
||||
iterator.previous();
|
||||
mIndex--;
|
||||
|
||||
if (mNext != null) {
|
||||
removePage(mNext);
|
||||
@@ -394,22 +400,20 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
mCurrent = mPrevious;
|
||||
mPrevious = null;
|
||||
|
||||
if (iterator.hasPrevious()) {
|
||||
iterator.mark();
|
||||
iterator.previous();
|
||||
if (mIndex > 0) {
|
||||
mPrevious = mGalleryView.obtainPage();
|
||||
iterator.bind(mPrevious);
|
||||
mAdapter.bind(mPrevious, mIndex - 1);
|
||||
mGalleryView.addComponent(mPrevious);
|
||||
iterator.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void pageNext() {
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
if (!iterator.hasNext()) {
|
||||
GalleryView.Adapter adapter = mAdapter;
|
||||
int size = adapter.size();
|
||||
if (mIndex >= size - 1) {
|
||||
return;
|
||||
}
|
||||
iterator.next();
|
||||
mIndex++;
|
||||
|
||||
if (mPrevious != null) {
|
||||
removePage(mPrevious);
|
||||
@@ -418,13 +422,10 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
mCurrent = mNext;
|
||||
mNext = null;
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
iterator.mark();
|
||||
iterator.next();
|
||||
if (mIndex < size - 1) {
|
||||
mNext = mGalleryView.obtainPage();
|
||||
iterator.bind(mNext);
|
||||
adapter.bind(mNext, mIndex + 1);
|
||||
mGalleryView.addComponent(mNext);
|
||||
iterator.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,7 +590,7 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
public void onFling(float velocityX, float velocityY) {
|
||||
if (mCurrent == null || mOffset != 0 || !mCurrent.getImageView().isLoaded() ||
|
||||
!mCurrent.getImageView().canFling()) {
|
||||
return;
|
||||
@@ -625,7 +626,7 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
@Override
|
||||
public void onDataChanged() {
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", mIterator, null);
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", mAdapter, null);
|
||||
|
||||
// Cancel all animations
|
||||
cancelAllAnimations();
|
||||
@@ -639,19 +640,28 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GalleryPageView findPageById(int id) {
|
||||
if (mCurrent != null && mCurrent.getId() == id) {
|
||||
public GalleryPageView findPageByIndex(int index) {
|
||||
if (mCurrent != null && mCurrent.getIndex() == index) {
|
||||
return mCurrent;
|
||||
}
|
||||
if (mPrevious != null && mPrevious.getId() == id) {
|
||||
if (mPrevious != null && mPrevious.getIndex() == index) {
|
||||
return mPrevious;
|
||||
}
|
||||
if (mNext != null && mNext.getId() == id) {
|
||||
if (mNext != null && mNext.getIndex() == index) {
|
||||
return mNext;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentIndex() {
|
||||
if (mCurrent != null) {
|
||||
return mCurrent.getIndex();
|
||||
} else {
|
||||
return GalleryPageView.INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
class SmoothScroller extends Animation {
|
||||
|
||||
private int mDx;
|
||||
@@ -701,7 +711,7 @@ public class PagerLayoutManager extends GalleryView.LayoutManager {
|
||||
private int mDy;
|
||||
private int mLastX;
|
||||
private int mLastY;
|
||||
private int[] mTemp = new int[2];
|
||||
private final int[] mTemp = new int[2];
|
||||
|
||||
public PageFling(Context context) {
|
||||
super(context);
|
||||
|
||||
@@ -20,47 +20,57 @@ import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.hippo.ehviewer.gallery.GalleryProvider;
|
||||
import com.hippo.gl.view.GLView;
|
||||
import com.hippo.gl.widget.GLEdgeView;
|
||||
import com.hippo.gl.widget.GLProgressView;
|
||||
import com.hippo.gl.widget.GLTextureView;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.LayoutUtils;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
// TODO Not safe ! Ensure change component in render thread
|
||||
public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
private static final String TAG = ScrollLayoutManager.class.getSimpleName();
|
||||
|
||||
private static final int INTERVAL = 24;
|
||||
|
||||
private static final float RESERVATIONS = 0.5f;
|
||||
|
||||
private GalleryView.PageIterator mIterator;
|
||||
private GalleryView.Adapter mAdapter;
|
||||
|
||||
private GLProgressView mProgress;
|
||||
private String mErrorStr;
|
||||
private GLTextureView mErrorView;
|
||||
private LinkedList<GalleryPageView> mPages = new LinkedList<>();
|
||||
private final LinkedList<GalleryPageView> mPages = new LinkedList<>();
|
||||
|
||||
private int mOffset;
|
||||
private int mDeltaX;
|
||||
private int mDeltaY;
|
||||
private int mFirstShownLoadedPageIndex = GalleryPageView.INVALID_INDEX;
|
||||
|
||||
private int mInterval;
|
||||
private int mProgressSpec;
|
||||
private final int mInterval;
|
||||
|
||||
private PageFling mPageFling;
|
||||
private final PageFling mPageFling;
|
||||
|
||||
public ScrollLayoutManager(Context context, @NonNull GalleryView galleryView,
|
||||
int interval) {
|
||||
// Current index
|
||||
private int mIndex;
|
||||
|
||||
private final BottomState mBottomState = new BottomState();
|
||||
|
||||
class BottomState {
|
||||
int bottom;
|
||||
boolean hasNext;
|
||||
}
|
||||
|
||||
public ScrollLayoutManager(Context context, @NonNull GalleryView galleryView) {
|
||||
super(galleryView);
|
||||
|
||||
mInterval = interval;
|
||||
mProgressSpec = GLView.MeasureSpec.makeMeasureSpec(GLView.LayoutParams.WRAP_CONTENT,
|
||||
GLView.LayoutParams.WRAP_CONTENT);
|
||||
mInterval = LayoutUtils.dp2pix(context, INTERVAL);
|
||||
mPageFling = new PageFling(context);
|
||||
}
|
||||
|
||||
@@ -68,6 +78,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
mOffset = 0;
|
||||
mDeltaX = 0;
|
||||
mDeltaY = 0;
|
||||
mFirstShownLoadedPageIndex = GalleryPageView.INVALID_INDEX;
|
||||
}
|
||||
|
||||
private void cancelAllAnimations() {
|
||||
@@ -75,10 +86,10 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(GalleryView.PageIterator iterator) {
|
||||
AssertUtils.assertEquals("The ScrollLayoutManager is attached", mIterator, null);
|
||||
AssertUtils.assertNotEquals("The iterator is null", iterator, null);
|
||||
mIterator = iterator;
|
||||
public void onAttach(GalleryView.Adapter adapter) {
|
||||
AssertUtils.assertEquals("The ScrollLayoutManager is attached", mAdapter, null);
|
||||
AssertUtils.assertNotEquals("The iterator is null", adapter, null);
|
||||
mAdapter = adapter;
|
||||
// Reset parameters
|
||||
resetParameters();
|
||||
}
|
||||
@@ -102,7 +113,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
private void removePage(@NonNull GalleryPageView page) {
|
||||
mGalleryView.removeComponent(page);
|
||||
mIterator.unbind(page);
|
||||
mAdapter.unbind(page);
|
||||
mGalleryView.releasePage(page);
|
||||
}
|
||||
|
||||
@@ -114,8 +125,8 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GalleryView.PageIterator onDetach() {
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", mIterator, null);
|
||||
public GalleryView.Adapter onDetach() {
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", mAdapter, null);
|
||||
|
||||
// Cancel all animations
|
||||
cancelAllAnimations();
|
||||
@@ -126,17 +137,18 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
removeAllPages();
|
||||
|
||||
// Clear iterator
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
mIterator = null;
|
||||
GalleryView.Adapter iterator = mAdapter;
|
||||
mAdapter = null;
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
private void fillPages() {
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
GalleryView.Adapter adapter = mAdapter;
|
||||
GalleryView galleryView = mGalleryView;
|
||||
int width = galleryView.getWidth();
|
||||
int height = galleryView.getHeight();
|
||||
int size = adapter.size();
|
||||
|
||||
int minY = (int) (-height * RESERVATIONS);
|
||||
|
||||
@@ -151,10 +163,10 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
pages.remove();
|
||||
// Update offset
|
||||
mOffset = nextTop;
|
||||
if (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
if (mIndex < size - 1) {
|
||||
mIndex++;
|
||||
} else {
|
||||
Log.e(TAG, "iterator should has next");
|
||||
Log.e(TAG, "The page is out of show range, but it has no next page");
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
@@ -167,11 +179,11 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
int widthSpec = GLView.MeasureSpec.makeMeasureSpec(width, GLView.MeasureSpec.EXACTLY);
|
||||
int heightSpec = GLView.MeasureSpec.makeMeasureSpec(height, GLView.MeasureSpec.UNSPECIFIED);
|
||||
int pageSize = 0;
|
||||
while (y >= minY && iterator.hasPrevious()) {
|
||||
iterator.previous();
|
||||
while (y >= minY && mIndex > 0) {
|
||||
mIndex--;
|
||||
|
||||
GalleryPageView page = galleryView.obtainPage();
|
||||
iterator.bind(page);
|
||||
mAdapter.bind(page, mIndex);
|
||||
galleryView.addComponent(page);
|
||||
mPages.add(0, page);
|
||||
|
||||
@@ -190,20 +202,27 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
mOffset = y;
|
||||
|
||||
// Fix offset, ensure it is not positive
|
||||
if (mOffset > 0) {
|
||||
int offset = mOffset;
|
||||
// Update offset
|
||||
mOffset = 0;
|
||||
oldOffset -= offset;
|
||||
// Translate pages
|
||||
pages = mPages.iterator();
|
||||
for (int i = 0; i < pageSize; i++) {
|
||||
pages.next().bounds().offset(0, -offset);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill from oldOffset
|
||||
iterator.mark();
|
||||
// Go to oldOffset
|
||||
int maxY = (int) (height * (1 + RESERVATIONS));
|
||||
y = oldOffset;
|
||||
pages = mPages.iterator();
|
||||
for (int i = 0; i < pageSize; i++) {
|
||||
if (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
} else {
|
||||
Log.e(TAG, "iterator should has next");
|
||||
}
|
||||
pages.next();
|
||||
}
|
||||
int index = mIndex + pageSize;
|
||||
// Do fill
|
||||
while (true) {
|
||||
GalleryPageView page;
|
||||
@@ -211,7 +230,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
pages = null;
|
||||
// New page
|
||||
page = galleryView.obtainPage();
|
||||
iterator.bind(page);
|
||||
mAdapter.bind(page, index);
|
||||
galleryView.addComponent(page);
|
||||
mPages.add(page);
|
||||
} else {
|
||||
@@ -234,13 +253,12 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
y += mInterval;
|
||||
|
||||
// Check has next
|
||||
if (!iterator.hasNext()) {
|
||||
if (index >= size - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
iterator.next();
|
||||
index++;
|
||||
}
|
||||
iterator.reset();
|
||||
|
||||
// Remove useless page
|
||||
while (mPages.size() > pageSize) {
|
||||
@@ -250,15 +268,36 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onFill() {
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
public void onFill() {
|
||||
GalleryView.Adapter adapter = mAdapter;
|
||||
GalleryView galleryView = mGalleryView;
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", iterator, null);
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", adapter, null);
|
||||
|
||||
int height = galleryView.getHeight();
|
||||
String errorStr = iterator.getError();
|
||||
int size = adapter.size();
|
||||
String errorStr = adapter.getError();
|
||||
|
||||
if (size == GalleryProvider.STATE_WAIT) { // Wait here, show progress bar
|
||||
// Remove error view and all pages
|
||||
removeErrorView();
|
||||
removeAllPages();
|
||||
|
||||
// Ensure progress
|
||||
if (mProgress == null) {
|
||||
mProgress = galleryView.obtainProgress();
|
||||
galleryView.addComponent(mProgress);
|
||||
}
|
||||
|
||||
// Place progress center
|
||||
placeCenter(mProgress);
|
||||
} else if (size <= GalleryProvider.STATE_ERROR || size == 0) { // Get error or empty, show error text
|
||||
// Ensure error is not null
|
||||
if (0 == size) {
|
||||
errorStr = galleryView.getEmptyStr();
|
||||
} else if (null == errorStr) {
|
||||
errorStr = galleryView.getDefaultErrorStr();
|
||||
}
|
||||
|
||||
if (errorStr != null) {
|
||||
// Remove progress and all pages
|
||||
removeProgress();
|
||||
removeAllPages();
|
||||
@@ -277,53 +316,93 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
// Place error view center
|
||||
placeCenter(mErrorView);
|
||||
} else if (iterator.isWaiting()) {
|
||||
// Remove error view and all pages
|
||||
removeErrorView();
|
||||
removeAllPages();
|
||||
|
||||
// Ensure progress
|
||||
if (mProgress == null) {
|
||||
mProgress = galleryView.obtainProgress();
|
||||
galleryView.addComponent(mProgress);
|
||||
}
|
||||
|
||||
// Place progress center
|
||||
placeCenter(mProgress);
|
||||
} else {
|
||||
LinkedList<GalleryPageView> pages = mPages;
|
||||
|
||||
// Remove progress and error view
|
||||
removeProgress();
|
||||
removeErrorView();
|
||||
|
||||
// Find first shown loaded page
|
||||
// Ensure index in range
|
||||
int index = mIndex;
|
||||
if (index < 0) {
|
||||
Log.e(TAG, "index < 0, index = " + index);
|
||||
index = 0;
|
||||
mIndex = index;
|
||||
removeAllPages();
|
||||
} else if (index >= size) {
|
||||
Log.e(TAG, "index >= size, index = " + index + ", size = " + size);
|
||||
index = size - 1;
|
||||
mIndex = index;
|
||||
removeAllPages();
|
||||
}
|
||||
|
||||
// Find first shown loaded page top
|
||||
GalleryPageView firstShownLoadedPage = null;
|
||||
int firstShownLoadedPageTop = mOffset;
|
||||
for (GalleryPageView page : mPages) {
|
||||
// Check first shown loaded page
|
||||
if (page.isLoaded()) {
|
||||
Rect bound = page.bounds();
|
||||
int pageTop = bound.top;
|
||||
int pageBottom = bound.bottom;
|
||||
if ((pageTop > 0 && pageTop < height) || (pageBottom > 0 && pageBottom < height)) {
|
||||
if (mFirstShownLoadedPageIndex != GalleryPageView.INVALID_INDEX) {
|
||||
for (GalleryPageView page : pages) {
|
||||
// Check first shown loaded page
|
||||
if (mFirstShownLoadedPageIndex == page.getIndex()) {
|
||||
firstShownLoadedPage = page;
|
||||
break;
|
||||
}
|
||||
firstShownLoadedPageTop += page.getHeight() + mInterval;
|
||||
}
|
||||
firstShownLoadedPageTop += page.getHeight() + mInterval;
|
||||
}
|
||||
|
||||
fillPages();
|
||||
|
||||
// TODO Avoid page not fill bottom, but has previous
|
||||
|
||||
// Ensure first shown loaded page top is the same
|
||||
if (firstShownLoadedPage != null && firstShownLoadedPage.isAttachedToRoot()) {
|
||||
if (firstShownLoadedPage != null && mFirstShownLoadedPageIndex == firstShownLoadedPage.getIndex()) {
|
||||
int newTop = firstShownLoadedPage.bounds().top;
|
||||
if (firstShownLoadedPageTop != newTop) {
|
||||
mOffset += firstShownLoadedPageTop - newTop;
|
||||
fillPages();
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid page not fill bottom, but has previous
|
||||
while (true) {
|
||||
int bottomDist = height - pages.getLast().bounds().bottom;
|
||||
int topDist = 0 - pages.getFirst().bounds().top;
|
||||
if (bottomDist > 0 && topDist > 0) {
|
||||
int translate = Math.min(bottomDist, topDist);
|
||||
// Update offset
|
||||
mOffset += translate;
|
||||
// Translate pages
|
||||
for (GalleryPageView page : pages) {
|
||||
page.bounds().offset(0, translate);
|
||||
}
|
||||
// Break if no previous
|
||||
if (mIndex <= 0) {
|
||||
break;
|
||||
}
|
||||
// Refill pages
|
||||
fillPages();
|
||||
// Break if last page bottom fit gallery view bottom
|
||||
if (bottomDist <= topDist) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get first shown loaded image
|
||||
mFirstShownLoadedPageIndex = GalleryPageView.INVALID_INDEX;
|
||||
for (GalleryPageView page : mPages) {
|
||||
// Check first shown loaded page
|
||||
//if (page.isLoaded()) {
|
||||
Rect bound = page.bounds();
|
||||
int pageTop = bound.top;
|
||||
int pageBottom = bound.bottom;
|
||||
if ((pageTop > 0 && pageTop < height) || (pageBottom > 0 && pageBottom < height)) {
|
||||
mFirstShownLoadedPageIndex = page.getIndex();
|
||||
break;
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,13 +457,32 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void getBottomState() {
|
||||
List<GalleryPageView> pages = mPages;
|
||||
int bottom = mOffset;
|
||||
int i = 0;
|
||||
for (GalleryPageView page : pages) {
|
||||
if (i != 0) {
|
||||
bottom += mInterval;
|
||||
}
|
||||
bottom += page.getHeight();
|
||||
i++;
|
||||
}
|
||||
boolean hasNext = mIndex + pages.size() < mAdapter.size();
|
||||
|
||||
BottomState bottomState = mBottomState;
|
||||
bottomState.bottom = bottom;
|
||||
bottomState.hasNext = hasNext;
|
||||
}
|
||||
|
||||
// True for get top or bottom
|
||||
private boolean scrollInternal(float dx, float dy, boolean fling, float x, float y) {
|
||||
if (mPages.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int height = mGalleryView.getHeight();
|
||||
GalleryView galleryView = mGalleryView;
|
||||
int height = galleryView.getHeight();
|
||||
boolean requestFill = false;
|
||||
int remainY = (int) dy;
|
||||
boolean result = false;
|
||||
@@ -392,7 +490,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
while (remainY != 0) {
|
||||
if (remainY < 0) { // Try to show top
|
||||
int limit;
|
||||
if (mIterator.hasPrevious()) {
|
||||
if (mIndex > 0) {
|
||||
limit = (int) (-height * RESERVATIONS);
|
||||
} else {
|
||||
limit = 0;
|
||||
@@ -405,10 +503,10 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
mDeltaX = 0;
|
||||
mDeltaY = 0;
|
||||
} else {
|
||||
if (mIterator.hasPrevious()) {
|
||||
if (mIndex > 0) {
|
||||
mOffset = limit;
|
||||
remainY = remainY + limit - mOffset;
|
||||
onFill();
|
||||
galleryView.forceFill();
|
||||
requestFill = false;
|
||||
mDeltaX = 0;
|
||||
mDeltaY = 0;
|
||||
@@ -425,23 +523,10 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
}
|
||||
} else { // Try to show bottom
|
||||
int bottom = mOffset;
|
||||
boolean hasNext = true;
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
iterator.mark();
|
||||
for (int i = 0, size = mPages.size(); i < size; i++) {
|
||||
if (i != 0) {
|
||||
bottom += mInterval;
|
||||
}
|
||||
bottom += mPages.get(i).getHeight();
|
||||
if (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
} else {
|
||||
hasNext = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator.reset();
|
||||
getBottomState();
|
||||
BottomState bottomState = mBottomState;
|
||||
int bottom = bottomState.bottom;
|
||||
boolean hasNext = bottomState.hasNext;
|
||||
|
||||
int limit;
|
||||
if (hasNext) {
|
||||
@@ -462,7 +547,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
if (hasNext) {
|
||||
mOffset -= bottom - limit;
|
||||
remainY = remainY + limit - bottom;
|
||||
onFill();
|
||||
galleryView.forceFill();
|
||||
requestFill = false;
|
||||
mDeltaX = 0;
|
||||
mDeltaY = 0;
|
||||
@@ -493,60 +578,26 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
scrollInternal(dx, dy, false, x, y);
|
||||
}
|
||||
|
||||
private boolean hasNextPage() {
|
||||
boolean hasNext = true;
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
iterator.mark();
|
||||
|
||||
for (int i = 0, size = mPages.size(); i < size; i++) {
|
||||
if (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
} else {
|
||||
hasNext = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iterator.reset();
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
public void onFling(float velocityX, float velocityY) {
|
||||
if (mPages.size() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int maxY;
|
||||
if (mIterator.hasPrevious()) {
|
||||
if (mIndex > 0) {
|
||||
maxY = Integer.MAX_VALUE;
|
||||
} else {
|
||||
maxY = -mOffset;
|
||||
}
|
||||
|
||||
int bottom = mOffset;
|
||||
boolean hasNext = true;
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
iterator.mark();
|
||||
for (int i = 0, size = mPages.size(); i < size; i++) {
|
||||
if (i != 0) {
|
||||
bottom += mInterval;
|
||||
}
|
||||
bottom += mPages.get(i).getHeight();
|
||||
if (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
} else {
|
||||
hasNext = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator.reset();
|
||||
|
||||
getBottomState();
|
||||
BottomState bottomState = mBottomState;
|
||||
int minY;
|
||||
if (hasNext) {
|
||||
if (bottomState.hasNext) {
|
||||
minY = Integer.MIN_VALUE;
|
||||
} else {
|
||||
minY = mGalleryView.getHeight() - bottom;
|
||||
minY = mGalleryView.getHeight() - bottomState.bottom;
|
||||
}
|
||||
|
||||
mPageFling.startFling((int) velocityX, 0, 0,
|
||||
@@ -571,7 +622,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
@Override
|
||||
public void onDataChanged() {
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", mIterator, null);
|
||||
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", mAdapter, null);
|
||||
|
||||
// Cancel all animations
|
||||
cancelAllAnimations();
|
||||
@@ -585,16 +636,29 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GalleryPageView findPageById(int id) {
|
||||
for (int i = 0, n = mPages.size(); i < n; i++) {
|
||||
GalleryPageView page = mPages.get(i);
|
||||
if (page.getId() == id) {
|
||||
public GalleryPageView findPageByIndex(int index) {
|
||||
for (GalleryPageView page : mPages) {
|
||||
if (page.getIndex() == index) {
|
||||
return page;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentIndex() {
|
||||
int height = mGalleryView.getHeight();
|
||||
for (GalleryPageView page : mPages) {
|
||||
Rect bound = page.bounds();
|
||||
int pageTop = bound.top;
|
||||
int pageBottom = bound.bottom;
|
||||
if ((pageTop > 0 && pageTop < height) || (pageBottom > 0 && pageBottom < height)) {
|
||||
return page.getIndex();
|
||||
}
|
||||
}
|
||||
return GalleryPageView.INVALID_INDEX;
|
||||
}
|
||||
|
||||
class PageFling extends Fling {
|
||||
|
||||
private int mVelocityX;
|
||||
@@ -661,26 +725,13 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
|
||||
|
||||
@Override
|
||||
protected void onFinish() {
|
||||
boolean topEdge = !mIterator.hasPrevious() && mOffset >= 0;
|
||||
int index = mIndex;
|
||||
|
||||
int bottom = mOffset;
|
||||
boolean hasNext = true;
|
||||
GalleryView.PageIterator iterator = mIterator;
|
||||
iterator.mark();
|
||||
for (int i = 0, size = mPages.size(); i < size; i++) {
|
||||
if (i != 0) {
|
||||
bottom += mInterval;
|
||||
}
|
||||
bottom += mPages.get(i).getHeight();
|
||||
if (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
} else {
|
||||
hasNext = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator.reset();
|
||||
boolean bottomEdge = !hasNext && bottom <= mGalleryView.getHeight();
|
||||
boolean topEdge = index <= 0 && mOffset >= 0;
|
||||
|
||||
getBottomState();
|
||||
BottomState bottomState = mBottomState;
|
||||
boolean bottomEdge = !bottomState.hasNext && bottomState.bottom <= mGalleryView.getHeight();
|
||||
|
||||
if (topEdge && bottomEdge) {
|
||||
return;
|
||||
|
||||
@@ -22,10 +22,12 @@ import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.gallery.DirGalleryProvider;
|
||||
import com.hippo.ehviewer.gallery.EhGalleryProvider;
|
||||
@@ -37,13 +39,14 @@ import com.hippo.ehviewer.gallery.gl.GalleryView;
|
||||
import com.hippo.gl.glrenderer.ImageTexture;
|
||||
import com.hippo.gl.glrenderer.MovableTextTexture;
|
||||
import com.hippo.gl.view.GLRootView;
|
||||
import com.hippo.gl.view.GLView;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.yorozuya.IntIdGenerator;
|
||||
import com.hippo.util.SystemUiHelper;
|
||||
import com.hippo.widget.Slider;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class GalleryActivity extends AppCompatActivity implements GalleryProviderListener {
|
||||
public class GalleryActivity extends AppCompatActivity
|
||||
implements GalleryProviderListener, Slider.OnSetProgressListener {
|
||||
|
||||
public static final String ACTION_DIR = "dir";
|
||||
public static final String ACTION_ZIP = "zip";
|
||||
@@ -52,6 +55,7 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
public static final String KEY_ACTION = "action";
|
||||
public static final String KEY_FILENAME = "filename";
|
||||
public static final String KEY_GALLERY_INFO = "gallery_info";
|
||||
public static final String KEY_SHOWING = "showing";
|
||||
|
||||
private String mAction;
|
||||
private String mFilename;
|
||||
@@ -66,8 +70,19 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
private ImageTexture.Uploader mUploader;
|
||||
@Nullable
|
||||
private GalleryProvider mGalleryProvider;
|
||||
|
||||
@Nullable
|
||||
private SparseIntArray mIndexIdMap;
|
||||
private SystemUiHelper mSystemUiHelper;
|
||||
private boolean mSystemUiShowing = false;
|
||||
|
||||
@Nullable
|
||||
private View mSliderPanel;
|
||||
@Nullable
|
||||
private TextView mLeftText;
|
||||
@Nullable
|
||||
private TextView mRightText;
|
||||
@Nullable
|
||||
private Slider mSlider;
|
||||
|
||||
private void buildProvider() {
|
||||
if (mGalleryProvider != null) {
|
||||
@@ -116,6 +131,7 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
if (mGalleryInfo != null) {
|
||||
outState.putParcelable(KEY_GALLERY_INFO, mGalleryInfo);
|
||||
}
|
||||
outState.putBoolean(KEY_SHOWING, mSystemUiShowing);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,15 +155,33 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
GLRootView glRootView = (GLRootView) findViewById(R.id.gl_root_view);
|
||||
mGalleryProvider.setGLRoot(glRootView);
|
||||
mUploader = new ImageTexture.Uploader(glRootView);
|
||||
mIndexIdMap = new SparseIntArray();
|
||||
mPageTextTexture = MovableTextTexture.create(Typeface.DEFAULT,
|
||||
getResources().getDimensionPixelSize(R.dimen.gallery_page_text),
|
||||
getResources().getColor(R.color.secondary_text_dark),
|
||||
new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'});
|
||||
|
||||
mGalleryView = new GalleryView(this, new GalleryPageIterator(),
|
||||
mPageTextTexture, null, GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT);
|
||||
mGalleryView = new GalleryView(this, new GalleryAdapter(),
|
||||
mPageTextTexture, null, GalleryView.LAYOUT_MODE_TOP_TO_BOTTOM);
|
||||
glRootView.setContentPane(mGalleryView);
|
||||
|
||||
// System UI helper
|
||||
mSystemUiHelper = new SystemUiHelper(this, SystemUiHelper.LEVEL_IMMERSIVE,
|
||||
SystemUiHelper.FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES | SystemUiHelper.FLAG_IMMERSIVE_STICKY);
|
||||
if (savedInstanceState == null || !savedInstanceState.getBoolean(KEY_SHOWING, false)) {
|
||||
mSystemUiHelper.hide();
|
||||
mSystemUiShowing = false;
|
||||
} else {
|
||||
mSystemUiHelper.show();
|
||||
mSystemUiShowing = true;
|
||||
}
|
||||
|
||||
/*
|
||||
mSliderPanel = findViewById(R.id.slider_panel);
|
||||
mLeftText = (TextView) mSliderPanel.findViewById(R.id.left);
|
||||
mRightText = (TextView) mSliderPanel.findViewById(R.id.right);
|
||||
mSlider = (Slider) mSliderPanel.findViewById(R.id.slider);
|
||||
mSlider.setOnSetProgressListener(this);
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,13 +201,29 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
mGalleryProvider.stop();
|
||||
mGalleryProvider = null;
|
||||
}
|
||||
mIndexIdMap = null;
|
||||
|
||||
mLeftText = null;
|
||||
mRightText = null;
|
||||
mSlider = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
||||
if (hasFocus && mSystemUiHelper != null) {
|
||||
if (mSystemUiShowing) {
|
||||
mSystemUiHelper.show();
|
||||
} else {
|
||||
mSystemUiHelper.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
// Check volume
|
||||
if (false) { // TODO Setting.getVolumePage()
|
||||
if (Settings.getVolumePage()) {
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
// TODO do something
|
||||
return true;
|
||||
@@ -220,7 +270,7 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
// Check volume
|
||||
if (false) { // TODO Setting.getVolumePage()
|
||||
if (Settings.getVolumePage()) {
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
|
||||
keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
|
||||
return true;
|
||||
@@ -244,16 +294,25 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
}
|
||||
|
||||
private GalleryPageView findPageByIndex(int index) {
|
||||
if (mIndexIdMap == null || mGalleryView == null) {
|
||||
if (mGalleryView != null) {
|
||||
return mGalleryView.findPageByIndex(index);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
int id = mIndexIdMap.get(index, GLView.NO_ID);
|
||||
if (id == GLView.NO_ID) {
|
||||
return null;
|
||||
private void updateSlider(int size) {
|
||||
if (mSlider == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return mGalleryView.findPageById(id);
|
||||
if (size >= 0) {
|
||||
mSlider.setRange(1, size);
|
||||
|
||||
|
||||
} else {
|
||||
// TODO hide slider
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,6 +320,16 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
if (mGalleryView != null) {
|
||||
mGalleryView.onDataChanged();
|
||||
}
|
||||
/*
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mGalleryProvider != null) {
|
||||
updateSlider(mGalleryProvider.size());
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -309,97 +378,49 @@ public class GalleryActivity extends AppCompatActivity implements GalleryProvide
|
||||
}
|
||||
}
|
||||
|
||||
private class GalleryPageIterator extends GalleryView.PageIterator {
|
||||
|
||||
private IntIdGenerator mIdGenerator = new IntIdGenerator();
|
||||
private int mIndex = 0;
|
||||
private int mBackup = mIndex;
|
||||
|
||||
@Override
|
||||
public void mark() {
|
||||
mBackup = mIndex;
|
||||
@Override
|
||||
public void onSetProgress(Slider slider, int newProgress, int oldProgress,
|
||||
boolean byUser, boolean confirm) {
|
||||
if (confirm && mGalleryView != null) {
|
||||
//mGalleryView.goToPage(newProgress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
mIndex = mBackup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWaiting() {
|
||||
return mGalleryProvider != null && mGalleryProvider.size() == GalleryProvider.STATE_WAIT;
|
||||
}
|
||||
private class GalleryAdapter extends GalleryView.Adapter {
|
||||
|
||||
@Override
|
||||
public String getError() {
|
||||
if (mGalleryProvider == null) {
|
||||
return getString(R.string.error_no_provider);
|
||||
} else if (mGalleryProvider.size() == GalleryProvider.STATE_ERROR) {
|
||||
String error = mGalleryProvider.getError();
|
||||
if (error != null) {
|
||||
return error;
|
||||
} else {
|
||||
return getString(R.string.error_unknown);
|
||||
}
|
||||
} else if (mGalleryProvider.size() == 0) {
|
||||
return getString(R.string.error_empty);
|
||||
} else if (mGalleryProvider.size() <= GalleryProvider.STATE_ERROR) {
|
||||
return mGalleryProvider.getError();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return mGalleryProvider != null && mIndex < mGalleryProvider.size() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return mIndex > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next() {
|
||||
if (mGalleryProvider != null && mIndex >= mGalleryProvider.size() - 1) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
public int size() {
|
||||
if (mGalleryProvider == null) {
|
||||
return GalleryProvider.STATE_ERROR;
|
||||
} else {
|
||||
return mGalleryProvider.size();
|
||||
}
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void previous() {
|
||||
if (mIndex <= 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
mIndex--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onBind(GalleryPageView view) {
|
||||
public void onBind(GalleryPageView view, int index) {
|
||||
if (mGalleryProvider != null && mGalleryView != null) {
|
||||
mGalleryProvider.request(mIndex);
|
||||
mGalleryProvider.request(index);
|
||||
view.showInfo();
|
||||
view.setImage(null);
|
||||
view.setPage(mIndex + 1);
|
||||
view.setPage(index + 1);
|
||||
view.setProgress(GalleryPageView.PROGRESS_INDETERMINATE);
|
||||
view.setError(null, null);
|
||||
}
|
||||
|
||||
int id = mIdGenerator.nextId();
|
||||
if (mIndexIdMap != null) {
|
||||
mIndexIdMap.put(mIndex, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnbind(GalleryPageView view) {
|
||||
if (mIndexIdMap != null) {
|
||||
int index = mIndexIdMap.indexOfKey(view.getId());
|
||||
if (index >= 0) {
|
||||
mIndexIdMap.removeAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
view.setImage(null);
|
||||
view.setError(null, null);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.widget.ListAdapter;
|
||||
import com.hippo.app.AppCompatPreferenceActivity;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.ui.fragment.EhFragment;
|
||||
import com.hippo.ehviewer.ui.fragment.ReadFragment;
|
||||
import com.hippo.vector.VectorDrawable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@@ -46,6 +47,7 @@ public final class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
|
||||
private static final String[] ENTRY_FRAGMENTS = {
|
||||
EhFragment.class.getName(),
|
||||
ReadFragment.class.getName(),
|
||||
};
|
||||
|
||||
private class FakeLayoutInflater extends LayoutInflater {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2016 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.ehviewer.ui.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceFragment;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class ReadFragment extends PreferenceFragment {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.read_settings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.WindowManager;
|
||||
|
||||
/**
|
||||
* Helper for controlling the visibility of the System UI across the various API levels. To use
|
||||
* this API, instantiate an instance of this class with the required level. The level specifies the
|
||||
* extent to which the System UI's visibility is changed when you call {@link #hide()}
|
||||
* or {@link #toggle()}.
|
||||
*/
|
||||
public final class SystemUiHelper {
|
||||
|
||||
/**
|
||||
* In this level, the helper will toggle low profile mode.
|
||||
*/
|
||||
public static final int LEVEL_LOW_PROFILE = 0;
|
||||
|
||||
/**
|
||||
* In this level, the helper will toggle the visibility of the status bar.
|
||||
* If there is a navigation bar, it will toggle low profile mode.
|
||||
*/
|
||||
public static final int LEVEL_HIDE_STATUS_BAR = 1;
|
||||
|
||||
/**
|
||||
* In this level, the helper will toggle the visibility of the navigation bar
|
||||
* (if present and if possible) and status bar. In cases where the navigation
|
||||
* bar is present but cannot be hidden, it will toggle low profile mode.
|
||||
*/
|
||||
public static final int LEVEL_LEAN_BACK = 2;
|
||||
|
||||
/**
|
||||
* In this level, the helper will toggle the visibility of the navigation bar
|
||||
* (if present and if possible) and status bar, in an immersive mode. This means that the app
|
||||
* will continue to receive all touch events. The user can reveal the system bars with an
|
||||
* inward swipe along the region where the system bars normally appear.
|
||||
*
|
||||
* <p>The {@link #FLAG_IMMERSIVE_STICKY} flag can be used to control how the system bars are
|
||||
* displayed.
|
||||
*/
|
||||
public static final int LEVEL_IMMERSIVE = 3;
|
||||
|
||||
/**
|
||||
* When this flag is set, the
|
||||
* {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}
|
||||
* flag will be set on older devices, making the status bar "float" on top
|
||||
* of the activity layout. This is most useful when there are no controls at
|
||||
* the top of the activity layout.
|
||||
* <p>
|
||||
* This flag isn't used on newer devices because the <a
|
||||
* href="http://developer.android.com/design/patterns/actionbar.html">action
|
||||
* bar</a>, the most important structural element of an Android app, should
|
||||
* be visible and not obscured by the system UI.
|
||||
*/
|
||||
public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1;
|
||||
|
||||
/**
|
||||
* Used with {@link #LEVEL_IMMERSIVE}. When this flag is set, an inward swipe in the system
|
||||
* bars areas will cause the system bars to temporarily appear in a semi-transparent state,
|
||||
* but no flags are cleared, and your system UI visibility change listeners are not triggered.
|
||||
* The bars automatically hide again after a short delay, or if the user interacts with the
|
||||
* middle of the screen.
|
||||
*/
|
||||
public static final int FLAG_IMMERSIVE_STICKY = 0x2;
|
||||
|
||||
private static final String LOG_TAG = SystemUiHelper.class.getSimpleName();
|
||||
|
||||
private final SystemUiHelperImpl mImpl;
|
||||
|
||||
private final Handler mHandler;
|
||||
private final Runnable mHideRunnable;
|
||||
|
||||
/**
|
||||
* Construct a new SystemUiHelper.
|
||||
*
|
||||
* @param activity The Activity who's system UI should be changed
|
||||
* @param level The level of hiding. Should be either {@link #LEVEL_LOW_PROFILE},
|
||||
* {@link #LEVEL_HIDE_STATUS_BAR}, {@link #LEVEL_LEAN_BACK} or
|
||||
* {@link #LEVEL_IMMERSIVE}
|
||||
* @param flags Additional options. See {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES} and
|
||||
* {@link #FLAG_IMMERSIVE_STICKY}
|
||||
*/
|
||||
public SystemUiHelper(Activity activity, int level, int flags) {
|
||||
this(activity, level, flags, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new SystemUiHelper.
|
||||
*
|
||||
* @param activity The Activity who's system UI should be changed
|
||||
* @param level The level of hiding. Should be either {@link #LEVEL_LOW_PROFILE},
|
||||
* {@link #LEVEL_HIDE_STATUS_BAR}, {@link #LEVEL_LEAN_BACK} or
|
||||
* {@link #LEVEL_IMMERSIVE}
|
||||
* @param flags Additional options. See {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES} and
|
||||
* {@link #FLAG_IMMERSIVE_STICKY}
|
||||
* @param listener A listener which is called when the system visibility is changed
|
||||
*/
|
||||
public SystemUiHelper(Activity activity, int level, int flags,
|
||||
OnVisibilityChangeListener listener) {
|
||||
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mHideRunnable = new HideRunnable();
|
||||
|
||||
// Create impl
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
mImpl = new SystemUiHelperImplKK(activity, level, flags, listener);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
mImpl = new SystemUiHelperImplJB(activity, level, flags, listener);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
mImpl = new SystemUiHelperImplICS(activity, level, flags, listener);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
mImpl = new SystemUiHelperImplHC(activity, level, flags, listener);
|
||||
} else {
|
||||
mImpl = new SystemUiHelperImplBase(activity, level, flags, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the system UI is currently showing. What this means depends on the mode this
|
||||
* {@link SystemUiHelper} was instantiated with.
|
||||
*/
|
||||
public boolean isShowing() {
|
||||
return mImpl.isShowing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the system UI. What this means depends on the mode this {@link SystemUiHelper} was
|
||||
* instantiated with.
|
||||
*
|
||||
* <p>Any currently queued delayed hide requests will be removed.
|
||||
*/
|
||||
public void show() {
|
||||
// Ensure that any currently queued hide calls are removed
|
||||
removeQueuedRunnables();
|
||||
|
||||
mImpl.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the system UI. What this means depends on the mode this {@link SystemUiHelper} was
|
||||
* instantiated with.
|
||||
*
|
||||
* <p>Any currently queued delayed hide requests will be removed.
|
||||
*/
|
||||
public void hide() {
|
||||
// Ensure that any currently queued hide calls are removed
|
||||
removeQueuedRunnables();
|
||||
|
||||
mImpl.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that the system UI is hidden after a delay.
|
||||
*
|
||||
* <p>Any currently queued delayed hide requests will be removed.
|
||||
*
|
||||
* @param delayMillis The delay (in milliseconds) until the Runnable
|
||||
* will be executed.
|
||||
*/
|
||||
public void delayHide(long delayMillis) {
|
||||
// Ensure that any currently queued hide calls are removed
|
||||
removeQueuedRunnables();
|
||||
|
||||
mHandler.postDelayed(mHideRunnable, delayMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle whether the system UI is displayed.
|
||||
*/
|
||||
public void toggle() {
|
||||
if (mImpl.isShowing()) {
|
||||
mImpl.hide();
|
||||
} else {
|
||||
mImpl.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeQueuedRunnables() {
|
||||
// Ensure that any currently queued hide calls are removed
|
||||
mHandler.removeCallbacks(mHideRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback interface used to listen for system UI visibility changes.
|
||||
*/
|
||||
public interface OnVisibilityChangeListener {
|
||||
/**
|
||||
* Called when the system UI visibility has changed.
|
||||
*
|
||||
* @param visible True if the system UI is visible.
|
||||
*/
|
||||
public void onVisibilityChange(boolean visible);
|
||||
}
|
||||
|
||||
static abstract class SystemUiHelperImpl {
|
||||
|
||||
final Activity mActivity;
|
||||
final int mLevel;
|
||||
final int mFlags;
|
||||
final OnVisibilityChangeListener mOnVisibilityChangeListener;
|
||||
|
||||
boolean mIsShowing = true;
|
||||
|
||||
SystemUiHelperImpl(Activity activity, int level, int flags,
|
||||
OnVisibilityChangeListener onVisibilityChangeListener) {
|
||||
mActivity = activity;
|
||||
mLevel = level;
|
||||
mFlags = flags;
|
||||
mOnVisibilityChangeListener = onVisibilityChangeListener;
|
||||
}
|
||||
|
||||
abstract void show();
|
||||
abstract void hide();
|
||||
|
||||
boolean isShowing() {
|
||||
return mIsShowing;
|
||||
}
|
||||
|
||||
void setIsShowing(boolean isShowing) {
|
||||
mIsShowing = isShowing;
|
||||
|
||||
if (mOnVisibilityChangeListener != null) {
|
||||
mOnVisibilityChangeListener.onVisibilityChange(mIsShowing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base implementation. Used on API level 10 and below.
|
||||
*/
|
||||
static class SystemUiHelperImplBase extends SystemUiHelperImpl {
|
||||
|
||||
SystemUiHelperImplBase(Activity activity, int level, int flags,
|
||||
OnVisibilityChangeListener onVisibilityChangeListener) {
|
||||
super(activity, level, flags, onVisibilityChangeListener);
|
||||
|
||||
if ((mFlags & SystemUiHelper.FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) != 0) {
|
||||
mActivity.getWindow().addFlags(
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void show() {
|
||||
if (mLevel > SystemUiHelper.LEVEL_LOW_PROFILE) {
|
||||
mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
setIsShowing(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void hide() {
|
||||
if (mLevel > SystemUiHelper.LEVEL_LOW_PROFILE) {
|
||||
mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
setIsShowing(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class HideRunnable implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.util;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
class SystemUiHelperImplHC extends SystemUiHelper.SystemUiHelperImpl
|
||||
implements View.OnSystemUiVisibilityChangeListener {
|
||||
|
||||
final View mDecorView;
|
||||
|
||||
SystemUiHelperImplHC(Activity activity, int level, int flags,
|
||||
SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) {
|
||||
super(activity, level, flags, onVisibilityChangeListener);
|
||||
|
||||
mDecorView = activity.getWindow().getDecorView();
|
||||
mDecorView.setOnSystemUiVisibilityChangeListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void show() {
|
||||
mDecorView.setSystemUiVisibility(createShowFlags());
|
||||
}
|
||||
|
||||
@Override
|
||||
void hide() {
|
||||
mDecorView.setSystemUiVisibility(createHideFlags());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSystemUiVisibilityChange(int visibility) {
|
||||
if ((visibility & createTestFlags()) != 0) {
|
||||
onSystemUiHidden();
|
||||
} else {
|
||||
onSystemUiShown();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onSystemUiShown() {
|
||||
ActionBar ab = mActivity.getActionBar();
|
||||
if (ab != null) {
|
||||
ab.show();
|
||||
}
|
||||
|
||||
mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
setIsShowing(true);
|
||||
}
|
||||
|
||||
protected void onSystemUiHidden() {
|
||||
ActionBar ab = mActivity.getActionBar();
|
||||
if (ab != null) {
|
||||
ab.hide();
|
||||
}
|
||||
|
||||
mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
setIsShowing(false);
|
||||
}
|
||||
|
||||
protected int createShowFlags() {
|
||||
return View.STATUS_BAR_VISIBLE;
|
||||
}
|
||||
|
||||
protected int createHideFlags() {
|
||||
return View.STATUS_BAR_HIDDEN;
|
||||
}
|
||||
|
||||
protected int createTestFlags() {
|
||||
return View.STATUS_BAR_HIDDEN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.util;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
class SystemUiHelperImplICS extends SystemUiHelperImplHC {
|
||||
|
||||
SystemUiHelperImplICS(Activity activity, int level, int flags,
|
||||
SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) {
|
||||
super(activity, level, flags, onVisibilityChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int createShowFlags() {
|
||||
return View.SYSTEM_UI_FLAG_VISIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int createTestFlags() {
|
||||
if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) {
|
||||
// Intentionally override test flags.
|
||||
return View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
|
||||
}
|
||||
|
||||
return View.SYSTEM_UI_FLAG_LOW_PROFILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int createHideFlags() {
|
||||
int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
|
||||
|
||||
if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) {
|
||||
flag |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.util;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
class SystemUiHelperImplJB extends SystemUiHelperImplICS {
|
||||
|
||||
SystemUiHelperImplJB(Activity activity, int level, int flags,
|
||||
SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) {
|
||||
super(activity, level, flags, onVisibilityChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int createShowFlags() {
|
||||
int flag = super.createShowFlags();
|
||||
|
||||
if (mLevel >= SystemUiHelper.LEVEL_HIDE_STATUS_BAR) {
|
||||
flag |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
|
||||
|
||||
if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) {
|
||||
flag |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int createHideFlags() {
|
||||
int flag = super.createHideFlags();
|
||||
|
||||
if (mLevel >= SystemUiHelper.LEVEL_HIDE_STATUS_BAR) {
|
||||
flag |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||
|
||||
if (mLevel >= SystemUiHelper.LEVEL_LEAN_BACK) {
|
||||
flag |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSystemUiShown() {
|
||||
if (mLevel == SystemUiHelper.LEVEL_LOW_PROFILE) {
|
||||
// Manually show the action bar when in low profile mode.
|
||||
ActionBar ab = mActivity.getActionBar();
|
||||
if (ab != null) {
|
||||
ab.show();
|
||||
}
|
||||
}
|
||||
|
||||
setIsShowing(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSystemUiHidden() {
|
||||
if (mLevel == SystemUiHelper.LEVEL_LOW_PROFILE) {
|
||||
// Manually hide the action bar when in low profile mode.
|
||||
ActionBar ab = mActivity.getActionBar();
|
||||
if (ab != null) {
|
||||
ab.hide();
|
||||
}
|
||||
}
|
||||
|
||||
setIsShowing(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.util;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
class SystemUiHelperImplKK extends SystemUiHelperImplJB {
|
||||
|
||||
SystemUiHelperImplKK(Activity activity, int level, int flags,
|
||||
SystemUiHelper.OnVisibilityChangeListener onVisibilityChangeListener) {
|
||||
super(activity, level, flags, onVisibilityChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int createHideFlags() {
|
||||
int flag = super.createHideFlags();
|
||||
|
||||
if (mLevel == SystemUiHelper.LEVEL_IMMERSIVE) {
|
||||
// If the client requested immersive mode, and we're on Android 4.4
|
||||
// or later, add relevant flags. Applying HIDE_NAVIGATION without
|
||||
// IMMERSIVE prevents the activity from accepting all touch events,
|
||||
// so we only do this on Android 4.4 and later (where IMMERSIVE is
|
||||
// present).
|
||||
flag |= ((mFlags & SystemUiHelper.FLAG_IMMERSIVE_STICKY) != 0)
|
||||
? View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
: View.SYSTEM_UI_FLAG_IMMERSIVE;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.os.BatteryManager;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.drawable.BatteryDrawable;
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class BatteryView extends TextView {
|
||||
|
||||
private int mColor;
|
||||
private int mWarningColor;
|
||||
private int mCurrentColor;
|
||||
|
||||
private int mLevel = 0;
|
||||
private boolean mCharging = false;
|
||||
|
||||
private BatteryDrawable mDrawable;
|
||||
|
||||
private boolean mAttached = false;
|
||||
private boolean mIsChargerWorking = false;
|
||||
|
||||
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
@SuppressLint("SetTextI18n")
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
|
||||
* 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
|
||||
boolean charging = (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
|
||||
== BatteryManager.BATTERY_STATUS_CHARGING);
|
||||
|
||||
if (mLevel != level || mCharging != charging) {
|
||||
mLevel = level;
|
||||
mCharging = charging;
|
||||
if (mCharging && mLevel != 100) {
|
||||
startCharger();
|
||||
} else {
|
||||
stopCharger();
|
||||
mDrawable.setElect(mLevel);
|
||||
}
|
||||
|
||||
if (level <= BatteryDrawable.WARN_LIMIT && !charging) {
|
||||
setTextColor(mWarningColor);
|
||||
} else {
|
||||
setTextColor(mColor);
|
||||
}
|
||||
setText(mLevel + "%");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCharger = new Runnable() {
|
||||
|
||||
private int level = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
level += 2;
|
||||
if (level > 100) {
|
||||
level = 0;
|
||||
}
|
||||
mDrawable.setElect(level, false);
|
||||
getHandler().postDelayed(mCharger, 200);
|
||||
}
|
||||
};
|
||||
|
||||
public BatteryView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public BatteryView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BatteryView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
init();
|
||||
|
||||
TypedArray typedArray = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.BatteryView, defStyleAttr, 0);
|
||||
mColor = typedArray.getColor(R.styleable.BatteryView_color, Color.WHITE);
|
||||
mWarningColor = typedArray.getColor(R.styleable.BatteryView_warningColor, Color.RED);
|
||||
typedArray.recycle();
|
||||
|
||||
mDrawable.setColor(mColor);
|
||||
mDrawable.setWarningColor(mWarningColor);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mDrawable = new BatteryDrawable();
|
||||
int height = (int) getTextSize();
|
||||
mDrawable.setBounds(0, 0, (int) (height / 0.618f), height);
|
||||
setCompoundDrawables(mDrawable, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextColor(int color) {
|
||||
if (mCurrentColor == color) {
|
||||
return;
|
||||
}
|
||||
mCurrentColor = color;
|
||||
super.setTextColor(color);
|
||||
}
|
||||
|
||||
private void startCharger() {
|
||||
if (!mIsChargerWorking) {
|
||||
getHandler().post(mCharger);
|
||||
mIsChargerWorking = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void stopCharger() {
|
||||
if (mIsChargerWorking) {
|
||||
getHandler().removeCallbacks(mCharger);
|
||||
mIsChargerWorking = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
if (!mAttached) {
|
||||
mAttached = true;
|
||||
|
||||
registerReceiver();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
if (mAttached) {
|
||||
unregisterReceiver();
|
||||
stopCharger();
|
||||
mAttached = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReceiver() {
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
|
||||
}
|
||||
|
||||
private void unregisterReceiver() {
|
||||
getContext().unregisterReceiver(mIntentReceiver);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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;
|
||||
|
||||
final class DateUtils {
|
||||
|
||||
public static final char QUOTE = '\'';
|
||||
public static final char SECONDS = 's';
|
||||
|
||||
public static boolean hasSeconds(CharSequence inFormat) {
|
||||
return hasDesignator(inFormat, SECONDS);
|
||||
}
|
||||
|
||||
public static boolean hasDesignator(CharSequence inFormat, char designator) {
|
||||
if (inFormat == null) return false;
|
||||
|
||||
final int length = inFormat.length();
|
||||
|
||||
int c;
|
||||
int count;
|
||||
|
||||
for (int i = 0; i < length; i += count) {
|
||||
count = 1;
|
||||
c = inFormat.charAt(i);
|
||||
|
||||
if (c == QUOTE) {
|
||||
count = skipQuotedText(inFormat, i, length);
|
||||
} else if (c == designator) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int skipQuotedText(CharSequence s, int i, int len) {
|
||||
if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
int count = 1;
|
||||
// skip leading quote
|
||||
i++;
|
||||
|
||||
while (i < len) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == QUOTE) {
|
||||
count++;
|
||||
// QUOTEQUOTE -> QUOTE
|
||||
if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewDebug.ExportedProperty;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class TextClock extends TextView {
|
||||
|
||||
public static final CharSequence DEFAULT_FORMAT_12_HOUR = "hh:mm a";
|
||||
public static final CharSequence DEFAULT_FORMAT_24_HOUR;
|
||||
|
||||
static {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
DEFAULT_FORMAT_24_HOUR = "kk:mm";
|
||||
else
|
||||
DEFAULT_FORMAT_24_HOUR = "HH:mm";
|
||||
}
|
||||
|
||||
private CharSequence mFormat12;
|
||||
private CharSequence mFormat24;
|
||||
|
||||
@ExportedProperty
|
||||
private CharSequence mFormat;
|
||||
@ExportedProperty
|
||||
private boolean mHasSeconds;
|
||||
|
||||
private boolean mAttached;
|
||||
|
||||
private Calendar mTime;
|
||||
private String mTimeZone;
|
||||
|
||||
private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
|
||||
final String timeZone = intent.getStringExtra("time-zone");
|
||||
createTime(timeZone);
|
||||
}
|
||||
onTimeChanged();
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mTicker = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onTimeChanged();
|
||||
|
||||
long now = SystemClock.uptimeMillis();
|
||||
long next = now + (1000 - now % 1000);
|
||||
|
||||
getHandler().postAtTime(mTicker, next);
|
||||
}
|
||||
};
|
||||
|
||||
public TextClock(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public TextClock(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public TextClock(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
mFormat12 = DEFAULT_FORMAT_12_HOUR;
|
||||
mFormat24 = DEFAULT_FORMAT_24_HOUR;
|
||||
mTimeZone = TimeZone.getDefault().getID();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
createTime(mTimeZone);
|
||||
// Wait until onAttachedToWindow() to handle the ticker
|
||||
chooseFormat(false);
|
||||
}
|
||||
|
||||
private void createTime(String timeZone) {
|
||||
if (timeZone != null) {
|
||||
mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
|
||||
} else {
|
||||
mTime = Calendar.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
public CharSequence getFormat12Hour() {
|
||||
return mFormat12;
|
||||
}
|
||||
|
||||
public void setFormat12Hour(CharSequence format) {
|
||||
mFormat12 = format;
|
||||
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
public CharSequence getFormat24Hour() {
|
||||
return mFormat24;
|
||||
}
|
||||
|
||||
public void setFormat24Hour(CharSequence format) {
|
||||
mFormat24 = format;
|
||||
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
public boolean is24HourModeEnabled() {
|
||||
return DateFormat.is24HourFormat(getContext());
|
||||
}
|
||||
|
||||
public String getTimeZone() {
|
||||
return mTimeZone;
|
||||
}
|
||||
|
||||
public void setTimeZone(String timeZone) {
|
||||
mTimeZone = timeZone;
|
||||
|
||||
createTime(timeZone);
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
|
||||
* depending on whether the user has selected 24-hour format.
|
||||
*
|
||||
* Calling this method does not schedule or unschedule the time ticker.
|
||||
*/
|
||||
private void chooseFormat() {
|
||||
chooseFormat(true);
|
||||
}
|
||||
|
||||
public CharSequence getFormat() {
|
||||
return mFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
|
||||
* depending on whether the user has selected 24-hour format.
|
||||
*
|
||||
* @param handleTicker true if calling this method should schedule/unschedule the
|
||||
* time ticker, false otherwise
|
||||
*/
|
||||
private void chooseFormat(boolean handleTicker) {
|
||||
final boolean format24Requested = is24HourModeEnabled();
|
||||
|
||||
if (format24Requested) {
|
||||
mFormat = mFormat24;
|
||||
} else {
|
||||
mFormat = mFormat12;
|
||||
}
|
||||
|
||||
boolean hadSeconds = mHasSeconds;
|
||||
mHasSeconds = DateUtils.hasSeconds(mFormat);
|
||||
|
||||
if (handleTicker && mAttached && hadSeconds != mHasSeconds) {
|
||||
if (hadSeconds) getHandler().removeCallbacks(mTicker);
|
||||
else mTicker.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
if (!mAttached) {
|
||||
mAttached = true;
|
||||
|
||||
registerReceiver();
|
||||
registerObserver();
|
||||
|
||||
createTime(mTimeZone);
|
||||
|
||||
if (mHasSeconds) {
|
||||
mTicker.run();
|
||||
} else {
|
||||
onTimeChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
if (mAttached) {
|
||||
unregisterReceiver();
|
||||
unregisterObserver();
|
||||
|
||||
getHandler().removeCallbacks(mTicker);
|
||||
|
||||
mAttached = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReceiver() {
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
|
||||
filter.addAction(Intent.ACTION_TIME_TICK);
|
||||
filter.addAction(Intent.ACTION_TIME_CHANGED);
|
||||
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
|
||||
|
||||
getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
|
||||
}
|
||||
|
||||
private void registerObserver() {
|
||||
final ContentResolver resolver = getContext().getContentResolver();
|
||||
resolver.registerContentObserver(Settings.System.CONTENT_URI, true, mFormatChangeObserver);
|
||||
}
|
||||
|
||||
private void unregisterReceiver() {
|
||||
getContext().unregisterReceiver(mIntentReceiver);
|
||||
}
|
||||
|
||||
private void unregisterObserver() {
|
||||
final ContentResolver resolver = getContext().getContentResolver();
|
||||
resolver.unregisterContentObserver(mFormatChangeObserver);
|
||||
}
|
||||
|
||||
private void onTimeChanged() {
|
||||
mTime.setTimeInMillis(System.currentTimeMillis());
|
||||
setText(DateFormat.format(mFormat, mTime));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user