使用Fresco与StaggeredGridLayoutManager

时间:2015-11-16 22:03:26

标签: android android-layout android-recyclerview android-cardview fresco

我遵循this体面的教程,一切都很好用本地图像。当尝试从本地图像更改为我通过Fresco加载到SimpleDraweeView的图像时,我似乎无法让视图调整大小并在其他图像中错开。

我的布局看起来像这样(它是:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    card_view:cardUseCompatPadding="true"
    card_view:cardCornerRadius="8dp"
    android:layout_marginBottom="16dp">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/fresco_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            fresco:actualImageScaleType="fitXY"
            />
        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="13sp"
            android:text="@string/hello_world"
            android:textColor="#ffffff"
            android:layout_below="@+id/fresco_image"
            android:paddingBottom="8dp"
            android:paddingTop="8dp"
            android:gravity="center_horizontal"
            android:layout_alignParentBottom="true"
            android:background="#1976D2"/>
    </RelativeLayout>
</android.support.v7.widget.CardView>

以上内容夸大如下:

    <android.support.v7.widget.RecyclerView
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/text"
        android:scrollbars="vertical">
    </android.support.v7.widget.RecyclerView>

在我的受票人身上,我试过了:

  1. 将宽度或高度或两者设置为&#34; match_parent&#34;和&#34; wrap_content&#34;各种变化。 wrap_content设置似乎不是recommended
  2. 不同的方面口粮,但这似乎会导致图像裁剪并且所有尺寸/形状均匀(不交错)
  3. scaleType与上述内容的不同组合。
  4. 在受票人之外,我一直在查看GitHub的一些演示,但我似乎找不到任何交错观点的例子。

    我确定这只是设置正确组合的问题,但就我而言,我无法弄清楚这种组合恰好是什么。

    任何建议(或样品)都将受到赞赏!!

    更新 我们的后端实现返回每张图片的宽高比(以及宽度/高度)。我能够在SimpleDraweeView上设置宽高比,并且它尊重这些值:

    vDraweeView.setAspectRatio(fAspect);
    

    如果我不必这样做会更冷,但显然视图在图像完全加载之前不知道它的大小。虽然这可能是调整视图大小的好时机,但这可能会导致跳转显示......不可取!!

    这听起来不错吗?

3 个答案:

答案 0 :(得分:1)

由于SimpleDraweeView在下载之前不知道图像的大小(并且在最初绘制之后调整大小并不是为了改变UI的原因 - 也许是其他原因),我必须在下载图像之前设置宽高比。这假设您在下载图像之前知道纵横比...我们在这种情况下会这样做。我在recyclerview适配器中这样做了。

设置宽高比的命令:

vDraweeView.setAspectRatio(fAspect);

答案 1 :(得分:0)

您可以使用此替代WrapContentDraweeView类:

public class WrapContentDraweeView extends GenericDraweeView {

private PipelineDraweeControllerBuilderSupplier mDraweeControllerBuilderSupplier;
private PipelineDraweeControllerBuilder mSimpleDraweeControllerBuilder;


public WrapContentDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
    super(context, hierarchy);
    this.init(context, (AttributeSet) null);
}

public WrapContentDraweeView(Context context) {
    super(context);
    this.init(context, (AttributeSet) null);
}

public WrapContentDraweeView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.init(context, attrs);
}

public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.init(context, attrs);
}

@TargetApi(21)
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyleAttr,
                             int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    this.init(context, attrs);
}

private void init(Context context, @Nullable AttributeSet attrs) {

    if (!this.isInEditMode()) {
        mDraweeControllerBuilderSupplier = Fresco.getDraweeControllerBuilderSupplier();
        Preconditions.checkNotNull(mDraweeControllerBuilderSupplier,
                "SimpleDraweeView was not initialized!");
        this.mSimpleDraweeControllerBuilder = mDraweeControllerBuilderSupplier.get();
        if (attrs != null) {
            TypedArray gdhAttrs = context.obtainStyledAttributes(attrs,
                    R.styleable.SimpleDraweeView);

            try {
                if (gdhAttrs.hasValue(
                        R.styleable.SimpleDraweeView_actualImageUri)) {
                    this.setImageURI((Uri) Uri.parse(gdhAttrs.getString(
                            R.styleable.SimpleDraweeView_actualImageUri)),
                            (Object) null);
                } else if (gdhAttrs.hasValue(
                        R.styleable.SimpleDraweeView_actualImageResource)) {
                    int resId = gdhAttrs.getResourceId(
                            R.styleable.SimpleDraweeView_actualImageResource,
                            -1);

                }
            } finally {
                gdhAttrs.recycle();
            }
        }

    }
}

protected SimpleDraweeControllerBuilder getControllerBuilder() {
    return this.mSimpleDraweeControllerBuilder;
}

public void setImageURI(Uri uri) {
    this.setImageURI((Uri) uri, (Object) null);
}

public void setImageURI(@Nullable String uriString) {
    this.setImageURI((String) uriString, (Object) null);
}

public void setImageURI(Uri uri, @Nullable Object callerContext) {
    setAspectRatio(FrescoUtils.getAspectRatio(uri));
    ImageDecodeOptions decoderOptions = ImageDecodeOptions.newBuilder()
            .setDecodePreviewFrame(true)

            .build();
    ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri)

            .setLocalThumbnailPreviewsEnabled(true)
            .setImageDecodeOptions(decoderOptions)

            .setPostprocessor(new BasePostprocessor() {
                @Override
                public CloseableReference<Bitmap> process(Bitmap sourceBitmap,
                                                          PlatformBitmapFactory bitmapFactory) {
                    int height = sourceBitmap.getHeight()/2;
                    int width = sourceBitmap.getWidth()/2;
                    if (width / (float) height < 0.5f) {
                        CloseableReference<Bitmap> cropReference = null;
                        CloseableReference<Bitmap> scaledReference = null;
                        try {
                            cropReference = bitmapFactory
                                    .createBitmap(sourceBitmap, 0, 0, width,
                                            (int) (width / 1.66f));
                            scaledReference = bitmapFactory
                                    .createScaledBitmap(cropReference.get(), getWidth(),
                                            (int) (getWidth() / 1.66f), false);
                            Bitmap bm = scaledReference.get();
                            Canvas canvas = new Canvas(bm);
                            Bitmap badge = getBadgeBitmap("长图");
                            int padding = (int) (getResources().getDisplayMetrics().density
                                    * 16);
                            canvas.drawBitmap(badge, bm.getWidth() - badge.getWidth() - padding,
                                    bm.getHeight() - badge.getHeight() - padding, new Paint());
                            return super.process(bm, bitmapFactory);
                        } finally {
                            if (cropReference != null) {
                                cropReference.close();
                            }
                            if (scaledReference != null) {
                                scaledReference.close();
                            }
                        }
                    }
                    return super.process(sourceBitmap, bitmapFactory);
                }
            })

            .build();

    DraweeController controller = this.mSimpleDraweeControllerBuilder
            .setImageRequest(imageRequest)
            .setCallerContext(callerContext)
            .setOldController(this.getController())
            .setAutoPlayAnimations(true)
            .setControllerListener(FrescoUtils.createControllerListener(this, uri))
            .setOldController(this.getController())


            .build();
    this.setController(controller);
}

public void setImageURI(@Nullable String uriString, @Nullable Object callerContext) {
    Uri uri = uriString != null ? Uri.parse(uriString) : null;
    this.setImageURI(uri, callerContext);
}



public void setImageResource(int resId) {
    super.setImageResource(resId);
}


private Bitmap getBadgeBitmap(String badge) {

    final DisplayMetrics dm = getResources().getDisplayMetrics();
    final float density = dm.density;
    final float scaledDensity = dm.scaledDensity;
    final TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint
            .SUBPIXEL_TEXT_FLAG);
    textPaint.setColor(Color.WHITE);
    textPaint.setTypeface(Typeface.create("sans-serif-black", Typeface.NORMAL));
    textPaint.setTextSize(12 * scaledDensity);

    final float padding = 4 * density;
    final float cornerRadius = 2 * density;
    final Rect textBounds = new Rect();
    textPaint.getTextBounds(badge, 0, badge.length(), textBounds);
    final int height = (int) (padding + textBounds.height() + padding);
    final int width = (int) (padding + textBounds.width() + padding);
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    bitmap.setHasAlpha(true);
    final Canvas canvas = new Canvas(bitmap);
    final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    backgroundPaint.setColor(Color.DKGRAY);
    RectF rectF = new RectF(0, 0, width, height);
    canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, backgroundPaint);
    // punch out the badge word, leaving transparency
  //        textPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

    // 居中
    Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
    int baseline = (int) (rectF.centerY() - (fontMetrics.top + fontMetrics.bottom) / 2);
    textPaint.setTextAlign(Paint.Align.CENTER);
    canvas.drawText(badge, rectF.centerX(), baseline, textPaint);
    return bitmap;
}
}

然后在你的布局中使用WrapContentDraweeView而不是SimpleDraweeView 并使用您的包名而不是fresco包

<com.package.info.WrapContentDraweeView

       android:id="@+id/gridThumbnail"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"


    android:adjustViewBounds="true"
    fresco:placeholderImage="@drawable/placeholder"
    />

这比后端实现更好。

答案 2 :(得分:0)

我有类似的问题,但我正在使用Glide。无论如何,尝试使用下面的属性设置ImageView。我的StaggeredGridView有2列,效果很好。

           Glide.with(context)
                .load(url)
                .placeholder(R.drawable.transparent_placeholder)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .crossFade()
                .into(itemCover)

在加载图片时我必须做的其他事情就是使用PlaceHolder来加载图像。

function stateConfig($stateProvider) {
        $stateProvider.state('home', {
            parent: 'app',
            url: '/', //Change to ''
            data: {
                authorities: []
            },
            views: {
                'content@': {
                    templateUrl: 'app/home/home.html',
                    controller: 'HomeController',
                    controllerAs: 'vm'
                }
            }
        });