Last active
July 4, 2016 13:27
-
-
Save s1rius/50ce8b98d865f8184e28d4ab44f9bf97 to your computer and use it in GitHub Desktop.
Revisions
-
s1rius revised this gist
Jul 4, 2016 . 1 changed file with 0 additions and 39 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,39 +0,0 @@ -
s1rius created this gist
Jul 3, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,326 @@ package me.s1rius.multidrawee; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.drawable.ScalingUtils; import com.facebook.drawee.generic.GenericDraweeHierarchy; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.interfaces.DraweeController; import com.facebook.drawee.view.DraweeHolder; import com.facebook.drawee.view.MultiDraweeHolder; import com.facebook.imagepipeline.common.ResizeOptions; import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequestBuilder; import java.util.ArrayList; import java.util.List; public class MultiDraweeView extends View { public interface OnItemClickListener { void onPicClick(int picIndex, Rect itemRect); } public static final String TAG = MultiDraweeView.class.getSimpleName(); public static final boolean DBG = true; private static int MAX_DRAWEE_COUNT = 9; MultiDraweeHolder<GenericDraweeHierarchy> mMultiDraweeHolder; private int mColumnCount = 3; private int mSpaceSize; private int mDraweeSize; private List<String> mUris = new ArrayList<>(); private GestureDetector mGestureDetector; private OnItemClickListener mItemClickListener; private int drawnTimes; private int drawnDuration; public MultiDraweeView(Context context) { super(context); init(context); } public MultiDraweeView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public MultiDraweeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.mItemClickListener = onItemClickListener; } private void init(Context context) { mSpaceSize = (int)dipToPixels(context, 3f); GenericDraweeHierarchyBuilder hierarchyBuilder = new GenericDraweeHierarchyBuilder(getResources()) .setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP) .setFadeDuration(0) .setPlaceholderImage(R.color.colorAccent); mMultiDraweeHolder = new MultiDraweeHolder<>(); for (int i = 0; i < MAX_DRAWEE_COUNT; i++) { DraweeHolder<GenericDraweeHierarchy> draweeHolder = DraweeHolder.create(hierarchyBuilder.build(), context); draweeHolder.getTopLevelDrawable().setCallback(this); mMultiDraweeHolder.add(draweeHolder); } mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapConfirmed(MotionEvent e) { if (mItemClickListener != null) { if (mUris.size() == 1) { mItemClickListener.onPicClick(0, getBoundsFromIndex(0)); } else { float x = e.getX(); float y = e.getY(); int itemIndex = getIndexFromPoint(x, y); mItemClickListener.onPicClick(itemIndex, getBoundsFromIndex(itemIndex)); if (DBG) Log.i(TAG, "motionEvent x = " + x + " y = " + y); } } return super.onSingleTapConfirmed(e); } @Override public boolean onDown(MotionEvent e) { return getIndexFromPoint(e.getX(), e.getY()) >= 0; } }); } @Override public boolean onTouchEvent(MotionEvent event) { if (null != mGestureDetector) { return mGestureDetector.onTouchEvent(event); } return super.onTouchEvent(event); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { long start = System.currentTimeMillis(); int widthSize = MeasureSpec.getSize(widthMeasureSpec); mDraweeSize = (MeasureSpec.getSize(widthMeasureSpec) - mSpaceSize * (mColumnCount - 1)) / mColumnCount; int rowCount = mUris.size() / mColumnCount + (mUris.size() % mColumnCount == 0 ? 0 : 1); int heightSize = mDraweeSize * rowCount + mSpaceSize * (rowCount - 1); setMeasuredDimension(widthSize, heightSize); long end = System.currentTimeMillis(); long measureDuration = end - start; if (DBG) Log.i(TAG, this.hashCode() + " onMeasure" + measureDuration); } public void setImageUris(List<String> uris) { for (int i = 0; i < MAX_DRAWEE_COUNT; i++) { mMultiDraweeHolder.get(i).getTopLevelDrawable().setCallback(null); } drawnTimes = 0; drawnDuration = 0; this.mUris = uris; ResizeOptions options; if (uris != null && uris.size() > 0) { options = new ResizeOptions((int)dipToPixels(getContext(), 100f), (int)dipToPixels(getContext(), 100f)); for (int i = 0; i < uris.size(); i++) { ImageRequest imageRequest = null; if (i < uris.size()) { Uri uri = Uri.parse(uris.get(i)); if (DBG) Log.i(TAG, this.hashCode() + " set image url " + uri.toString()); imageRequest = ImageRequestBuilder .newBuilderWithSource(uri) .setResizeOptions(options) .setProgressiveRenderingEnabled(false) .build(); mMultiDraweeHolder.get(i).getHierarchy().setPlaceholderImage(R.color.colorAccent); } DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(imageRequest) .setOldController(mMultiDraweeHolder.get(i).getController()) .build(); mMultiDraweeHolder.get(i).setController(controller); mMultiDraweeHolder.get(i).getTopLevelDrawable().setCallback(this); } } requestLayout(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); attach(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); detach(); } @Override public void onStartTemporaryDetach() { super.onStartTemporaryDetach(); detach(); } @Override public void onFinishTemporaryDetach() { super.onFinishTemporaryDetach(); attach(); } void attach() { mMultiDraweeHolder.onAttach(); } void detach() { for (int i = 0; i < MAX_DRAWEE_COUNT; i++) { mMultiDraweeHolder.get(i).getTopLevelDrawable().setCallback(null); } mMultiDraweeHolder.onDetach(); } @Override protected void onDraw(Canvas canvas) { if (getMeasuredWidth() == 0 && getMeasuredHeight() == 0) { return; } long start = System.currentTimeMillis(); super.onDraw(canvas); int left = 0, top = 0; for (int i = 0; i < mUris.size(); i++) { Drawable drawable = mMultiDraweeHolder.get(i).getTopLevelDrawable(); if (i % mColumnCount == 0) { left = 0; } if (drawable != null) { drawable.setBounds(left, top, left + mDraweeSize, top + mDraweeSize); drawable.draw(canvas); } left += mDraweeSize + mSpaceSize; if (i % mColumnCount != 0 && i % mColumnCount == mColumnCount - 1) { top += mDraweeSize + mSpaceSize; } } long end = System.currentTimeMillis(); drawnTimes ++; drawnDuration += (end - start); if (DBG) Log.i(TAG, this.hashCode() + " onDraw() method duration = " + drawnDuration + "ms" + " draw " + drawnTimes + " times" + " uri count " + mUris.size()); } private Rect getBoundsFromIndex(int index) { Rect rect = new Rect(); int left = 0, top = 0; if (index >= 0) { for (int i = 0; i < mUris.size(); i++) { if (i % mColumnCount == 0) { left = 0; } if (mUris.size() == 1) { rect.set(left, top, left + getMeasuredWidth(), top + getMeasuredHeight()); break; } else if (i == index) { rect.set(left, top, left + mDraweeSize, top + mDraweeSize); break; } left += mDraweeSize + mSpaceSize; if (i % mColumnCount != 0 && i % mColumnCount == mColumnCount - 1) { top += mDraweeSize + mSpaceSize; } } } else { rect.set(left, top, left + getMeasuredWidth(), top + getMeasuredHeight()); } return rect; } private int getIndexFromPoint(float x, float y){ if (mUris.size() == 1) { return 0; } int rowIndex = 0, columnIndex = 0, itemIndex; for (int i = 0; i < mColumnCount; i++) { int left = mDraweeSize * i + mSpaceSize *i; int right = left + mDraweeSize; if (x >= left && x < right) { columnIndex = i; } } while (true) { int top = rowIndex * mDraweeSize + rowIndex * mSpaceSize; int bottom = top + mDraweeSize; if (y >= top && y < bottom) { break; } rowIndex ++; } itemIndex = rowIndex * mColumnCount + columnIndex; if (itemIndex >= mUris.size()) { itemIndex = -1; } return itemIndex; } @Override protected boolean verifyDrawable(Drawable who) { if (DBG) Log.i(TAG, this.hashCode() + "verifyDrawable"); return mMultiDraweeHolder.verifyDrawable(who) || super.verifyDrawable(who); } @Override public void invalidateDrawable(@NonNull Drawable drawable) { int dirtyIndex = -1; for (int i = 0; i < mMultiDraweeHolder.size(); i++) { if (drawable == mMultiDraweeHolder.get(i).getTopLevelDrawable()) { dirtyIndex = i; break; } } if (dirtyIndex != -1) { Rect invalidateRect = getBoundsFromIndex(dirtyIndex); if (invalidateRect.height() != 0 && invalidateRect.width() != 0) { invalidate(invalidateRect); if (DBG) Log.i(TAG, this.hashCode() + " drawable code " + drawable.hashCode() + " invalidateDrawable " + getBoundsFromIndex(dirtyIndex).flattenToString()); } } } public float dipToPixels(Context context, float dipValue) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics); } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,39 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/avatar" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="12dp" android:layout_marginTop="8dp" android:src="@mipmap/ic_launcher"/> <TextView android:id="@+id/title" android:layout_toRightOf="@id/avatar" android:layout_alignTop="@id/avatar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="12dp" android:textSize="22sp" android:textColor="@android:color/darker_gray" android:text="im a title"/> <me.s1rius.multidrawee.MultiDraweeView android:id="@+id/pic" android:layout_below="@id/title" android:layout_toRightOf="@id/avatar" android:layout_marginRight="12dp" android:layout_marginLeft="12dp" android:layout_marginTop="12dp" android:layout_marginBottom="8dp" android:layout_width="match_parent" android:layout_height="wrap_content"> </me.s1rius.multidrawee.MultiDraweeView> </RelativeLayout>