2015-10-27 28 views
3

我见过有关Material Design的Udacity讲座,并提到了使用RoundedBitmapDrawable来实现圆形视图。不过,我有一些麻烦,使其与Picasso工作。使用带有RoundedBitmapDrawable的毕加索

我不确定Picasso的工作原理,但我在文件存储中有大的非正方形图像。为此我使用Picasso如下:然而

Picasso.with(context).load(f).resize(densityDpi, densityDpi).centerInside().transform(new Transformation() { 
    @Override 
    public Bitmap transform(Bitmap source) { 
     Log.d("jano", "transformation running"); 
     RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(context.getResources(), source); 
     drawable.setCircular(true); 
     drawable.setCornerRadius(source.getWidth()/2.0f); 
     return drawable.getBitmap(); 
    } 

    @Override 
    public String key() { 
     return "circle"; 
    } 
}).into(imageView); 

图像被平方不带圆角(应该是圆形)。这就是我想要达到的目标。

是否有任何简单的方法来实现RoundedBitmapDrawable或我必须完全实现转换? (我在StackOverflow上看到)

请不要提交没有说明的答案,为什么它不能使用。我只是想知道这2个项目的组合(PicassoRoundedBitmapDrawable

+0

您已经实现转型,究竟是什么问题? – Blackbelt

+0

对不起,编辑...图像平方不圆,这是问题 – VizGhar

+0

看到[这里](https://github.com/kingargyle/adt-leanback-support/blob/master/support-v4/src /main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java),并找出'RoundedBitmapDrawable#getBitmap'返回的内容。 – pskink

回答

0

你可以用谷歌IO应用程序的BezelImageView与毕加索库工作得很好,只是这个类添加到您的项目,您可以直接开始使用它像任何其他imageview,但bezelImageView有2个额外的选项来指定圆形边框颜色,并可以绘制蒙版。链接到源代码here

BezelImageView.java

/* 
* Copyright 2014 Google Inc. All rights reserved. 
* 
* 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.google.samples.apps.iosched.ui.widget; 

import android.content.Context; 
import android.content.res.TypedArray; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.ColorMatrix; 
import android.graphics.ColorMatrixColorFilter; 
import android.graphics.Paint; 
import android.graphics.PorterDuff; 
import android.graphics.PorterDuffXfermode; 
import android.graphics.Rect; 
import android.graphics.RectF; 
import android.graphics.drawable.Drawable; 
import android.support.v4.view.ViewCompat; 
import android.util.AttributeSet; 
import android.widget.ImageView; 

import com.google.samples.apps.iosched.R; 

/** 
* An {@link android.widget.ImageView} that draws its contents inside a mask and draws a border 
* drawable on top. This is useful for applying a beveled look to image contents, but is also 
* flexible enough for use with other desired aesthetics. 
*/ 
public class BezelImageView extends ImageView { 
    private Paint mBlackPaint; 
    private Paint mMaskedPaint; 

    private Rect mBounds; 
    private RectF mBoundsF; 

    private Drawable mBorderDrawable; 
    private Drawable mMaskDrawable; 

    private ColorMatrixColorFilter mDesaturateColorFilter; 
    private boolean mDesaturateOnPress = false; 

    private boolean mCacheValid = false; 
    private Bitmap mCacheBitmap; 
    private int mCachedWidth; 
    private int mCachedHeight; 

    public BezelImageView(Context context) { 
     this(context, null); 
    } 

    public BezelImageView(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public BezelImageView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 

     // Attribute initialization. 
     final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BezelImageView, 
       defStyle, 0); 

     mMaskDrawable = a.getDrawable(R.styleable.BezelImageView_maskDrawable); 
     if (mMaskDrawable != null) { 
      mMaskDrawable.setCallback(this); 
     } 

     mBorderDrawable = a.getDrawable(R.styleable.BezelImageView_borderDrawable); 
     if (mBorderDrawable != null) { 
      mBorderDrawable.setCallback(this); 
     } 

     mDesaturateOnPress = a.getBoolean(R.styleable.BezelImageView_desaturateOnPress, 
       mDesaturateOnPress); 

     a.recycle(); 

     // Other initialization. 
     mBlackPaint = new Paint(); 
     mBlackPaint.setColor(0xff000000); 

     mMaskedPaint = new Paint(); 
     mMaskedPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 

     // Always want a cache allocated. 
     mCacheBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); 

     if (mDesaturateOnPress) { 
      // Create a desaturate color filter for pressed state. 
      ColorMatrix cm = new ColorMatrix(); 
      cm.setSaturation(0); 
      mDesaturateColorFilter = new ColorMatrixColorFilter(cm); 
     } 
    } 

    @Override 
    protected boolean setFrame(int l, int t, int r, int b) { 
     final boolean changed = super.setFrame(l, t, r, b); 
     mBounds = new Rect(0, 0, r - l, b - t); 
     mBoundsF = new RectF(mBounds); 

     if (mBorderDrawable != null) { 
      mBorderDrawable.setBounds(mBounds); 
     } 
     if (mMaskDrawable != null) { 
      mMaskDrawable.setBounds(mBounds); 
     } 

     if (changed) { 
      mCacheValid = false; 
     } 

     return changed; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if (mBounds == null) { 
      return; 
     } 

     int width = mBounds.width(); 
     int height = mBounds.height(); 

     if (width == 0 || height == 0) { 
      return; 
     } 

     if (!mCacheValid || width != mCachedWidth || height != mCachedHeight) { 
      // Need to redraw the cache. 
      if (width == mCachedWidth && height == mCachedHeight) { 
       // Have a correct-sized bitmap cache already allocated. Just erase it. 
       mCacheBitmap.eraseColor(0); 
      } else { 
       // Allocate a new bitmap with the correct dimensions. 
       mCacheBitmap.recycle(); 
       //noinspection AndroidLintDrawAllocation 
       mCacheBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
       mCachedWidth = width; 
       mCachedHeight = height; 
      } 

      Canvas cacheCanvas = new Canvas(mCacheBitmap); 
      if (mMaskDrawable != null) { 
       int sc = cacheCanvas.save(); 
       mMaskDrawable.draw(cacheCanvas); 
       mMaskedPaint.setColorFilter((mDesaturateOnPress && isPressed()) 
         ? mDesaturateColorFilter : null); 
       cacheCanvas.saveLayer(mBoundsF, mMaskedPaint, 
         Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG); 
       super.onDraw(cacheCanvas); 
       cacheCanvas.restoreToCount(sc); 
      } else if (mDesaturateOnPress && isPressed()) { 
       int sc = cacheCanvas.save(); 
       cacheCanvas.drawRect(0, 0, mCachedWidth, mCachedHeight, mBlackPaint); 
       mMaskedPaint.setColorFilter(mDesaturateColorFilter); 
       cacheCanvas.saveLayer(mBoundsF, mMaskedPaint, 
         Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG); 
       super.onDraw(cacheCanvas); 
       cacheCanvas.restoreToCount(sc); 
      } else { 
       super.onDraw(cacheCanvas); 
      } 

      if (mBorderDrawable != null) { 
       mBorderDrawable.draw(cacheCanvas); 
      } 
     } 

     // Draw from cache. 
     canvas.drawBitmap(mCacheBitmap, mBounds.left, mBounds.top, null); 
    } 

    @Override 
    protected void drawableStateChanged() { 
     super.drawableStateChanged(); 
     if (mBorderDrawable != null && mBorderDrawable.isStateful()) { 
      mBorderDrawable.setState(getDrawableState()); 
     } 
     if (mMaskDrawable != null && mMaskDrawable.isStateful()) { 
      mMaskDrawable.setState(getDrawableState()); 
     } 
     if (isDuplicateParentStateEnabled()) { 
      ViewCompat.postInvalidateOnAnimation(this); 
     } 
    } 

    @Override 
    public void invalidateDrawable(Drawable who) { 
     if (who == mBorderDrawable || who == mMaskDrawable) { 
      invalidate(); 
     } else { 
      super.invalidateDrawable(who); 
     } 
    } 

    @Override 
    protected boolean verifyDrawable(Drawable who) { 
     return who == mBorderDrawable || who == mMaskDrawable || super.verifyDrawable(who); 
    } 
} 

使用的布局。

<com.google.samples.apps.iosched.ui.widget.BezelImageView 
       android:id="@+id/session_photo" 
       android:layout_width="120dp" 
       android:layout_height="120dp" 
       android:layout_gravity="center" 
       android:scaleType="centerCrop" 
       android:src="@drawable/dp" 
       app:borderDrawable="@drawable/circle_stroke_only" 
       app:maskDrawable="@drawable/circle_blue" /> 

circle_blue.xml

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval" 
    > 
    <solid android:color="#00bcd4" /> 
</shape> 

circle_stroke_only.xml

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval"> 

    <stroke android:color="@color/theme_green" android:width="1dp"/> 

</shape> 
+0

今天晚些时候会检查这个参考。谢谢 – VizGhar

3

我尝试了很多做同样的,也没有工作...我猜是getBitmap过程中出现问题,无论如何,我解决了这样做: (请注意,主要区别在于我使用setImage作为drawable,而不是像我所说的转换为Bitmap)

Picasso.with(getContext()) 
    .load(mUser.user.profileImageUrl) 
    .into(mProfileImage, new Callback() { 
     @Override 
     public void onSuccess() { 
      Bitmap source = ((BitmapDrawable) mProfileImage.getDrawable()).getBitmap(); 
      RoundedBitmapDrawable drawable = 
        RoundedBitmapDrawableFactory.create(getContext().getResources(), source); 
      drawable.setCircular(true); 
      drawable.setCornerRadius(Math.max(source.getWidth()/2.0f, source.getHeight()/2.0f)); 
      mProfileImage.setImageDrawable(drawable); 
     } 

     @Override 
     public void onError() { 

     } 
    }); 
+0

伙计们,我的解决方案将与回调工作,但现在我明白了这个问题,并可以解释如何解决转换:RoundedBitmapDrawableFactory的.getBitmap()将返回您的原始位图,它保存原始状态,所以在应用圆形修改后,您将返回原始位图而不进行任何更改。你可以重载你的ImageView,在setDrawable上使用RoundedBitmapDrawableFactory做圆形的方法,但是你不能在setBitmap上做(因为你不能把它作为Bitmap,只有原始的而不是圆形的位图)。 Capiche? ;) –

0

我花了几个小时完全相同的问题。它返回相同的非圆形图像的原因是因为它首先传递了一个非圆形的位图。

RoundedBitmapDrawable文档:

getBitmap()

返回用于此可绘制来渲染位图。

所以它的意思是返回原始未转换的位图。

解决方案:没什么!最后我用一个伟大的图书馆picasso-transformationsCropCircleTransformation()

例子:

Picasso.with(mContext).load(url) 
      .transform(new CropCircleTransformation()) 
      .into(holder_image);