diff --git a/library/build.gradle b/library/build.gradle index a3a01ec3..ea542665 100755 --- a/library/build.gradle +++ b/library/build.gradle @@ -7,8 +7,9 @@ android { defaultConfig { minSdkVersion 4 targetSdkVersion 23 - versionCode 1 - versionName "1.0" + // use values from gradle.properties + versionCode=Long.valueOf(VERSION_CODE) + versionName=VERSION_NAME } } diff --git a/library/src/main/java/uk/co/senab/photoview/HugeImageLoader.java b/library/src/main/java/uk/co/senab/photoview/HugeImageLoader.java new file mode 100644 index 00000000..92a9f24e --- /dev/null +++ b/library/src/main/java/uk/co/senab/photoview/HugeImageLoader.java @@ -0,0 +1,101 @@ +package uk.co.senab.photoview; + +import android.annotation.TargetApi; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.opengl.GLES20; +import android.os.Build; + +import java.io.File; + +import javax.microedition.khronos.opengles.GL10; + +import uk.co.senab.photoview.log.LogManager; + +/** + * If image is bigger that available memory + * load a scaled down version. + * see http://developer.android.com/training/displaying-bitmaps/index.html. + * + * Created by k3b on 14.09.2015. + */ +public class HugeImageLoader { + public static final String LOG_TAG = "HugeImageLoader"; + + // let debug flag be dynamic, but still Proguard can be used to remove from + // release builds + public static boolean DEBUG = true; //!!! Log.isLoggable(LOG_TAG, Log.DEBUG); + + @TargetApi(Build.VERSION_CODES.FROYO) + public static int getMaxTextureSize() { + try { + int[] max = new int[1]; + new GLES20().glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, max, 0); + + if (max[0] > 0) { + return max[0]; + } + } catch (Exception ex) { + + } + return 4096; + } + + public static Bitmap loadImage(File file, int maxWidth, int maxHeight) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + // int imageHeight = options.outHeight; + // int imageWidth = options.outWidth; + // String imageType = options.outMimeType; + + int downscale = calculateInSampleSize(options, maxWidth, maxHeight); + options.inSampleSize = downscale; + + if (DEBUG) { + Runtime r = Runtime.getRuntime(); + int width = options.outWidth; + int height = options.outHeight; + LogManager.getLogger().d( + LOG_TAG, + "loadImage(" + + "\n\t'" + file + + "', " + width + + "x" + height + + ", max=" + maxWidth + + "x" + maxHeight + + ", size=" + (width*height*4/1024) + + "k, " + + "\n\tmemory(total/free/avail)=(" + r.totalMemory()/1024 + "k,"+ r.freeMemory()/1024+ "k,"+ r.maxMemory()/1024 + + "k) ) " + + "\n\t==> " + width/downscale + + "x" + height/downscale + + ", size=" + (width*height*4/1024/downscale/downscale) + + "k, scale=" + downscale); + } + + // Decode bitmap with inSampleSize set + options.inJustDecodeBounds = false; + return BitmapFactory.decodeFile(file.getAbsolutePath(), options); + } + + private static int calculateInSampleSize( + BitmapFactory.Options options, int reqWidth, int reqHeight) { + // Raw height and width of image + int height = options.outHeight; + int width = options.outWidth; + int inSampleSize = 1; + + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while ((height > reqHeight) + || (width > reqWidth)) { + inSampleSize *= 2; + height /= 2; + width /= 2; + } + + return inSampleSize; + } +} diff --git a/library/src/main/java/uk/co/senab/photoview/PhotoView.java b/library/src/main/java/uk/co/senab/photoview/PhotoView.java index 5145820d..5e1c87af 100755 --- a/library/src/main/java/uk/co/senab/photoview/PhotoView.java +++ b/library/src/main/java/uk/co/senab/photoview/PhotoView.java @@ -25,12 +25,18 @@ import android.view.GestureDetector; import android.widget.ImageView; +import java.io.File; + import uk.co.senab.photoview.PhotoViewAttacher.OnMatrixChangedListener; import uk.co.senab.photoview.PhotoViewAttacher.OnPhotoTapListener; import uk.co.senab.photoview.PhotoViewAttacher.OnViewTapListener; public class PhotoView extends ImageView implements IPhotoView { + // for debug purposes + private static int lastDebugId = 1; + private final String mDebugId; + private PhotoViewAttacher mAttacher; private ScaleType mPendingScaleType; @@ -45,10 +51,19 @@ public PhotoView(Context context, AttributeSet attr) { public PhotoView(Context context, AttributeSet attr, int defStyle) { super(context, attr, defStyle); + // for debug purposes + this.mDebugId = "PhotoView#" + (++lastDebugId); + super.setScaleType(ScaleType.MATRIX); init(); } + // for debug purposes + @Override + public String toString() { + return mDebugId; + } + protected void init() { if (null == mAttacher || null == mAttacher.getImageView()) { mAttacher = new PhotoViewAttacher(this); @@ -153,7 +168,7 @@ public void setScaleLevels(float minimumScale, float mediumScale, float maximumS public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); if (null != mAttacher) { - mAttacher.update(); + mAttacher.update("setImageDrawable"); } } @@ -161,7 +176,7 @@ public void setImageDrawable(Drawable drawable) { public void setImageResource(int resId) { super.setImageResource(resId); if (null != mAttacher) { - mAttacher.update(); + mAttacher.update("setImageResource"); } } @@ -169,7 +184,7 @@ public void setImageResource(int resId) { public void setImageURI(Uri uri) { super.setImageURI(uri); if (null != mAttacher) { - mAttacher.update(); + mAttacher.update("setImageURI"); } } @@ -255,6 +270,7 @@ public void setOnSingleFlingListener(PhotoViewAttacher.OnSingleFlingListener onS @Override protected void onDetachedFromWindow() { mAttacher.cleanup(); + mAttacher = null; // else memory leak super.onDetachedFromWindow(); } @@ -263,4 +279,9 @@ protected void onAttachedToWindow() { init(); super.onAttachedToWindow(); } + + /** k3b 20150913 #10: Faster initial loading: initially the view is loaded with low res image. on first zoom it is reloaded with this uri */ + public void setImageReloadFile(File file) { + mAttacher.setImageReloadFile(file); + } } \ No newline at end of file diff --git a/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java b/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java index 5edfdf21..38e0dc67 100755 --- a/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java +++ b/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java @@ -25,6 +25,8 @@ import android.support.annotation.Nullable; import android.support.v4.view.MotionEventCompat; import android.util.Log; + +import android.os.Build; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; @@ -35,7 +37,9 @@ import android.view.animation.Interpolator; import android.widget.ImageView; import android.widget.ImageView.ScaleType; +import android.widget.Toast; +import java.io.File; import java.lang.ref.WeakReference; import uk.co.senab.photoview.gestures.OnGestureListener; @@ -51,12 +55,17 @@ public class PhotoViewAttacher implements IPhotoView, View.OnTouchListener, OnGestureListener, ViewTreeObserver.OnGlobalLayoutListener { - private static final String LOG_TAG = "PhotoViewAttacher"; + public static final String LOG_TAG = "PhotoViewAttacher"; // let debug flag be dynamic, but still Proguard can be used to remove from // release builds private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG); + static final Interpolator sInterpolator = new AccelerateDecelerateInterpolator(); + + /** my android 4.4 cannot process images bigger than 4096*4096. -1 means must be calculated from openGL */ + private static int MAX_IMAGE_DIMENSION = -1; // will be set to 4096 + private Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); int ZOOM_DURATION = DEFAULT_ZOOM_DURATION; @@ -74,6 +83,11 @@ public class PhotoViewAttacher implements IPhotoView, View.OnTouchListener, private boolean mAllowParentInterceptOnEdge = true; private boolean mBlockParentIntercept = false; + /** k3b 20150913 #10: Faster initial loading: initially the view is loaded with low res image. on first zoom it is reloaded with this uri */ + private File mImageReloadFile = null; + private double mLastFocusX = Double.NaN; + private double mLastFocusY = Double.NaN; + private static void checkZoomLevels(float minZoom, float midZoom, float maxZoom) { if (minZoom >= midZoom) { @@ -251,6 +265,10 @@ public void cleanup() { return; // cleanup already done } + if (DEBUG) { + LogManager.getLogger().d(LOG_TAG,"cleanup"); + } + final ImageView imageView = mImageView.get(); if (null != imageView) { @@ -302,7 +320,7 @@ public boolean setDisplayMatrix(Matrix finalMatrix) { } mSuppMatrix.set(finalMatrix); - setImageViewMatrix(getDrawMatrix()); + setImageViewMatrix(getDrawMatrix(), "setDisplayMatrix"); checkMatrixBounds(); return true; @@ -310,9 +328,9 @@ public boolean setDisplayMatrix(Matrix finalMatrix) { public void setBaseRotation(final float degrees) { mBaseRotation = degrees % 360; - update(); + update("setBaseRotation"); setRotationBy(mBaseRotation); - checkAndDisplayMatrix(); + checkAndDisplayMatrix("setBaseRotation"); } /** @@ -321,19 +339,19 @@ public void setBaseRotation(final float degrees) { @Override public void setPhotoViewRotation(float degrees) { mSuppMatrix.setRotate(degrees % 360); - checkAndDisplayMatrix(); + checkAndDisplayMatrix("setPhotoViewRotation"); } @Override public void setRotationTo(float degrees) { mSuppMatrix.setRotate(degrees % 360); - checkAndDisplayMatrix(); + checkAndDisplayMatrix("setRotationTo"); } @Override public void setRotationBy(float degrees) { mSuppMatrix.postRotate(degrees % 360); - checkAndDisplayMatrix(); + checkAndDisplayMatrix("setRotationBy"); } public ImageView getImageView() { @@ -391,7 +409,7 @@ public void onDrag(float dx, float dy) { ImageView imageView = getImageView(); mSuppMatrix.postTranslate(dx, dy); - checkAndDisplayMatrix(); + checkAndDisplayMatrix("onDrag"); /** * Here we decide whether to let the ImageView's parent to start taking @@ -454,21 +472,28 @@ public void onGlobalLayout() { */ if (top != mIvTop || bottom != mIvBottom || left != mIvLeft || right != mIvRight) { + float lastScale = getScale(); // Update our base matrix, as the bounds have changed - updateBaseMatrix(imageView.getDrawable()); + updateBaseMatrix(imageView.getDrawable(), "onGlobalLayout mZoomEnabled=true"); // Update values as something has changed mIvTop = top; mIvRight = right; mIvBottom = bottom; mIvLeft = left; + + if (!Double.isNaN(mLastFocusX)) { + // try to restore current zoom/focus + onScale(lastScale, (float) mLastFocusX, (float) mLastFocusY); + } } } else { - updateBaseMatrix(imageView.getDrawable()); + updateBaseMatrix(imageView.getDrawable(), "onGlobalLayout mZoomEnabled=false"); } } } + /** invoked by the guesture detector */ @Override public void onScale(float scaleFactor, float focusX, float focusY) { if (DEBUG) { @@ -478,12 +503,42 @@ public void onScale(float scaleFactor, float focusX, float focusY) { scaleFactor, focusX, focusY)); } - if ((getScale() < mMaxScale || scaleFactor < 1f) && (getScale() > mMinScale || scaleFactor > 1f)) { + /** k3b 20150913 #10: Faster initial loading: initially the view is loaded with low res image. on first zoom it is reloaded with this uri */ + if (mImageReloadFile != null) { + ImageView imageView = getImageView(); + if (imageView != null) { + if (DEBUG) { + // !!! + LogManager.getLogger().d( + LOG_TAG, + "onScale: Reloading image from " + mImageReloadFile); + } + try { + if (MAX_IMAGE_DIMENSION < 0) { + MAX_IMAGE_DIMENSION = (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) ? 4096 : HugeImageLoader.getMaxTextureSize(); + } + imageView.setImageBitmap(HugeImageLoader.loadImage(mImageReloadFile.getAbsoluteFile(), MAX_IMAGE_DIMENSION, MAX_IMAGE_DIMENSION)); + } catch (OutOfMemoryError e) { + String errorMessage = imageView.getContext().getString(R.string.err_low_memory, mImageReloadFile); + Toast.makeText(imageView.getContext(), errorMessage, Toast.LENGTH_LONG).show(); + + LogManager.getLogger().e( + LOG_TAG, + "onScale: Not enought memory to reloading image from " + mImageReloadFile + " failed: " + e.getMessage()); + } + + mImageReloadFile = null; // either success or error: do not try it again + } + } + + if (getScale() < mMaxScale || scaleFactor < 1f) { if (null != mScaleChangeListener) { mScaleChangeListener.onScaleChange(scaleFactor, focusX, focusY); } + mLastFocusX=focusX; + mLastFocusY=focusY; mSuppMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY); - checkAndDisplayMatrix(); + checkAndDisplayMatrix("onScale"); } } @@ -594,7 +649,7 @@ public void setOnPhotoTapListener(OnPhotoTapListener listener) { } @Nullable - OnPhotoTapListener getOnPhotoTapListener() { + public OnPhotoTapListener getOnPhotoTapListener() { return mPhotoTapListener; } @@ -604,7 +659,7 @@ public void setOnViewTapListener(OnViewTapListener listener) { } @Nullable - OnViewTapListener getOnViewTapListener() { + public PhotoViewAttacher.OnViewTapListener getOnViewTapListener() { return mViewTapListener; } @@ -645,7 +700,7 @@ public void setScale(float scale, float focalX, float focalY, focalX, focalY)); } else { mSuppMatrix.setScale(scale, scale, focalX, focalY); - checkAndDisplayMatrix(); + checkAndDisplayMatrix("setScale"); } } } @@ -664,17 +719,17 @@ public void setScaleType(ScaleType scaleType) { mScaleType = scaleType; // Finally update - update(); + update("setScaleType"); } } @Override public void setZoomable(boolean zoomable) { mZoomEnabled = zoomable; - update(); + update("setZoomable"); } - public void update() { + public void update(String why) { ImageView imageView = getImageView(); if (null != imageView) { @@ -683,16 +738,16 @@ public void update() { setImageViewScaleTypeMatrix(imageView); // Update the base matrix using the current drawable - updateBaseMatrix(imageView.getDrawable()); + updateBaseMatrix(imageView.getDrawable(), why); } else { // Reset the Matrix... - resetMatrix(); + resetMatrix(why); } } } /** - * Like {@link #getDisplayMatrix()}, but allows the user to provide a matrix to copy the values into to reduce object allocation + * Like {@link #getDisplayMatrix(Matrix)}, but allows the user to provide a matrix to copy the values into to reduce object allocation * @param matrix target matrix to copy to */ @Override @@ -722,10 +777,11 @@ private void cancelFling() { /** * Helper method that simply checks the Matrix, and then displays the result + * @param why */ - private void checkAndDisplayMatrix() { + private void checkAndDisplayMatrix(String why) { if (checkMatrixBounds()) { - setImageViewMatrix(getDrawMatrix()); + setImageViewMatrix(getDrawMatrix(), why); } } @@ -858,18 +914,23 @@ private float getValue(Matrix matrix, int whichValue) { /** * Resets the Matrix back to FIT_CENTER, and then displays it.s + * @param why */ - private void resetMatrix() { + private void resetMatrix(String why) { mSuppMatrix.reset(); setRotationBy(mBaseRotation); - setImageViewMatrix(getDrawMatrix()); + setImageViewMatrix(getDrawMatrix(), why+ "-resetMatrix"); checkMatrixBounds(); } - private void setImageViewMatrix(Matrix matrix) { + private void setImageViewMatrix(Matrix matrix, String why) { ImageView imageView = getImageView(); if (null != imageView) { + if (DEBUG) { + LogManager.getLogger().d(LOG_TAG,"setImageViewMatrix " + why); + } + checkImageViewScaleType(); imageView.setImageMatrix(matrix); @@ -887,8 +948,9 @@ private void setImageViewMatrix(Matrix matrix) { * Calculate Matrix for FIT_CENTER * * @param d - Drawable being displayed + * @param why */ - private void updateBaseMatrix(Drawable d) { + private void updateBaseMatrix(Drawable d, String why) { ImageView imageView = getImageView(); if (null == imageView || null == d) { return; @@ -951,7 +1013,7 @@ private void updateBaseMatrix(Drawable d) { } } - resetMatrix(); + resetMatrix(why); } private int getImageViewWidth(ImageView imageView) { @@ -966,6 +1028,12 @@ private int getImageViewHeight(ImageView imageView) { return imageView.getHeight() - imageView.getPaddingTop() - imageView.getPaddingBottom(); } + /** k3b 20150913 #10: Faster initial loading: initially the view is loaded with low res image. on first zoom it is reloaded with this uri + * @param imageReloadURI*/ + public void setImageReloadFile(File imageReloadURI) { + this.mImageReloadFile = imageReloadURI; + } + /** * Interface definition for a callback to be invoked when the internal Matrix has changed for * this View. @@ -1184,7 +1252,7 @@ public void run() { } mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY); - setImageViewMatrix(getDrawMatrix()); + setImageViewMatrix(getDrawMatrix(), "fling run"); mCurrentX = newX; mCurrentY = newY; diff --git a/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java b/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java index e14f463b..0cdf6898 100755 --- a/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java +++ b/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java @@ -25,7 +25,7 @@ public class CupcakeGestureDetector implements GestureDetector { protected OnGestureListener mListener; - private static final String LOG_TAG = "CupcakeGestureDetector"; + public static final String LOG_TAG = "CupcakeGestureDetector"; float mLastTouchX; float mLastTouchY; final float mTouchSlop; diff --git a/library/src/main/java/uk/co/senab/photoview/log/LogManager.java b/library/src/main/java/uk/co/senab/photoview/log/LogManager.java index eefdde39..048769e6 100755 --- a/library/src/main/java/uk/co/senab/photoview/log/LogManager.java +++ b/library/src/main/java/uk/co/senab/photoview/log/LogManager.java @@ -21,15 +21,25 @@ * class that holds the {@link Logger} for this library, defaults to {@link LoggerDefault} to send logs to android {@link Log} */ public final class LogManager { - + private static boolean sDebugEnabled = false; private static Logger logger = new LoggerDefault(); + private static Logger loggerDebug = new LoggerAndroidFull(); + + public static void enableDebug(boolean debugEnabled) + { + sDebugEnabled = debugEnabled; + } public static void setLogger(Logger newLogger) { + if (sDebugEnabled) { logger = newLogger; + } else { + loggerDebug = newLogger; + } } public static Logger getLogger() { - return logger; + return (sDebugEnabled) ? loggerDebug : logger; } } diff --git a/library/src/main/java/uk/co/senab/photoview/log/Logger.java b/library/src/main/java/uk/co/senab/photoview/log/Logger.java index 56295ec4..5324d75f 100755 --- a/library/src/main/java/uk/co/senab/photoview/log/Logger.java +++ b/library/src/main/java/uk/co/senab/photoview/log/Logger.java @@ -19,24 +19,98 @@ * interface for a logger class to replace the static calls to {@link android.util.Log} */ public interface Logger { - + /** + * Send a {@link android.util.Log#VERBOSE} log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ int v(String tag, String msg); + /** + * Send a {@link android.util.Log#VERBOSE} log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ int v(String tag, String msg, Throwable tr); + /** + * Send a {@link android.util.Log#DEBUG} log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ int d(String tag, String msg); + /** + * Send a {@link android.util.Log#DEBUG} log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ int d(String tag, String msg, Throwable tr); + /** + * Send an {@link android.util.Log#INFO} log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ int i(String tag, String msg); + /** + * Send a {@link android.util.Log#INFO} log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ int i(String tag, String msg, Throwable tr); + /** + * Send a {@link android.util.Log#WARN} log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ int w(String tag, String msg); + /** + * Send a {@link android.util.Log#WARN} log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ int w(String tag, String msg, Throwable tr); + /** + * Send an {@link android.util.Log#ERROR} log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ int e(String tag, String msg); + /** + * Send a {@link android.util.Log#ERROR} log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ int e(String tag, String msg, Throwable tr); } diff --git a/library/src/main/java/uk/co/senab/photoview/log/LoggerAndroidFull.java b/library/src/main/java/uk/co/senab/photoview/log/LoggerAndroidFull.java new file mode 100644 index 00000000..8b65170d --- /dev/null +++ b/library/src/main/java/uk/co/senab/photoview/log/LoggerAndroidFull.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright 2011, 2012 Chris Banes. + * + * 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 uk.co.senab.photoview.log; + +import android.util.Log; + +/** + * Helper class to redirect {@link LogManager#logger} to android {@link Log} for all log levels + */ +public class LoggerAndroidFull implements Logger { + + @Override + public int v(String tag, String msg) { + return Log.v(tag, msg); + } + + @Override + public int v(String tag, String msg, Throwable tr) { + return Log.v(tag, msg, tr); + } + + @Override + public int d(String tag, String msg) { + return Log.d(tag, msg); + } + + @Override + public int d(String tag, String msg, Throwable tr) { + return Log.d(tag, msg, tr); + } + + @Override + public int i(String tag, String msg) { + return Log.i(tag, msg); + } + + @Override + public int i(String tag, String msg, Throwable tr) { + return Log.i(tag, msg, tr); + } + + @Override + public int w(String tag, String msg) { + return Log.w(tag, msg); + } + + @Override + public int w(String tag, String msg, Throwable tr) { + return Log.w(tag, msg, tr); + } + + @Override + public int e(String tag, String msg) { + return Log.e(tag, msg); + } + + @Override + public int e(String tag, String msg, Throwable tr) { + return Log.e(tag, msg, tr); + } + + +} diff --git a/library/src/main/java/uk/co/senab/photoview/log/LoggerDefault.java b/library/src/main/java/uk/co/senab/photoview/log/LoggerDefault.java index f827f4a8..fd913859 100755 --- a/library/src/main/java/uk/co/senab/photoview/log/LoggerDefault.java +++ b/library/src/main/java/uk/co/senab/photoview/log/LoggerDefault.java @@ -18,38 +18,39 @@ import android.util.Log; /** - * Helper class to redirect {@link LogManager#logger} to {@link Log} + * Helper class to redirect {@link LogManager#logger} to android {@link Log} for log info (if enabled) warnm, error */ public class LoggerDefault implements Logger { + private static boolean logInfo = false; @Override public int v(String tag, String msg) { - return Log.v(tag, msg); + return 0; } @Override public int v(String tag, String msg, Throwable tr) { - return Log.v(tag, msg, tr); + return 0; } @Override public int d(String tag, String msg) { - return Log.d(tag, msg); + return 0; } @Override public int d(String tag, String msg, Throwable tr) { - return Log.d(tag, msg, tr); + return 0; } @Override public int i(String tag, String msg) { - return Log.i(tag, msg); + return (!logInfo) ? 0 : Log.i(tag, msg); } @Override public int i(String tag, String msg, Throwable tr) { - return Log.i(tag, msg, tr); + return (!logInfo) ? 0 : Log.i(tag, msg, tr); } @Override diff --git a/library/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml new file mode 100644 index 00000000..026c80b3 --- /dev/null +++ b/library/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Not enough memory available to load "%1$s". + \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle index 2512ce91..a853cefd 100755 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -8,8 +8,10 @@ android { applicationId "uk.co.senab.photoview.sample" minSdkVersion 8 targetSdkVersion 23 - versionCode 124 - versionName "1.2.4" + + // use values from gradle.properties + versionCode=Long.valueOf(VERSION_CODE) + versionName=VERSION_NAME } lintOptions { abortOnError false diff --git a/sample/src/main/java/uk/co/senab/photoview/sample/PicassoSampleActivity.java b/sample/src/main/java/uk/co/senab/photoview/sample/PicassoSampleActivity.java index c1555dae..cd5ac651 100644 --- a/sample/src/main/java/uk/co/senab/photoview/sample/PicassoSampleActivity.java +++ b/sample/src/main/java/uk/co/senab/photoview/sample/PicassoSampleActivity.java @@ -25,7 +25,7 @@ protected void onCreate(Bundle savedInstanceState) { .into(photoView, new Callback() { @Override public void onSuccess() { - attacher.update(); + attacher.update("Picasso-onSuccess()"); } @Override