Facebook Fresco, используя wrap_content
У меня есть куча чертежей, которые я хочу загрузить с помощью фрески, я хочу использовать размер wrap_content
для этих изображений, как я могу сделать это в xml с фреской? Или если xml невозможно, как вы это делаете в коде?
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/myImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fresco:placeholderImage="@mipmap/myImage"/>
Приведенный выше код не работает, если я не установил фиксированный размер.
Ответы
Ответ 1
Я часть команды Fresco, и я был тем, кто принял решение о дизайне не поддерживать wrap-content. Обоснование объясняется в документации . Но, короче говоря, проблема заключается в том, что вы не можете гарантировать, что изображение будет доступно сразу (возможно, вам придется сначала его получить), а это значит, что размер изображения должен измениться после поступления изображения. Это в большинстве случаев нежелательно, и вам следует, вероятно, пересмотреть свой интерфейс.
В любом случае, если вам действительно нужно/нужно это сделать, вы можете сделать это следующим образом:
void updateViewSize(@Nullable ImageInfo imageInfo) {
if (imageInfo != null) {
draweeView.getLayoutParams().width = imageInfo.getWidth();
draweeView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
draweeView.setAspectRatio((float) imageInfo.getWidth() / imageInfo.getHeight());
}
}
ControllerListener listener = new BaseControllerListener {
@Override
public void onIntermediateImageSet(String id, @Nullable ImageInfo imageInfo) {
updateViewSize(imageInfo);
}
@Override
public void onFinalImageSet(String id, @Nullable ImageInfo imageInfo, @Nullable Animatable animatable) {
updateViewSize(imageInfo);
}
};
DraweeController controller = draweeControllerBuilder
.setUri(uri)
.setControllerListener(listener)
.build();
draweeView.setController(controller);
Я написал этот код с верхней части головы, я его не протестировал. Но идея должна быть ясной, и она должна работать с небольшими корректировками.
Ответ 2
Основываясь на ответе @plamenko, я сделал индивидуальное представление следующим образом:
/**
* Works when either height or width is set to wrap_content
* The view is resized based on the image fetched
*/
public class WrapContentDraweeView extends SimpleDraweeView {
// we set a listener and update the view aspect ratio depending on the loaded image
private final ControllerListener listener = new BaseControllerListener<ImageInfo>() {
@Override
public void onIntermediateImageSet(String id, @Nullable ImageInfo imageInfo) {
updateViewSize(imageInfo);
}
@Override
public void onFinalImageSet(String id, @Nullable ImageInfo imageInfo, @Nullable Animatable animatable) {
updateViewSize(imageInfo);
}
};
public WrapContentDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
super(context, hierarchy);
}
public WrapContentDraweeView(Context context) {
super(context);
}
public WrapContentDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void setImageURI(Uri uri, Object callerContext) {
DraweeController controller = ((PipelineDraweeControllerBuilder)getControllerBuilder())
.setControllerListener(listener)
.setCallerContext(callerContext)
.setUri(uri)
.setOldController(getController())
.build();
setController(controller);
}
void updateViewSize(@Nullable ImageInfo imageInfo) {
if (imageInfo != null) {
setAspectRatio((float) imageInfo.getWidth() / imageInfo.getHeight());
}
}
}
Вы можете включить этот класс в XML
, пример использования:
<com.example.ui.views.WrapContentDraweeView
android:id="@+id/simple_drawee_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
Ответ 3
Нашел решение, расширив SimpleDraweeView
, он позволяет мне использовать wrap_content
, и он работает просто отлично! Как бы я ни помешал вам установить размер в setContentView
, и предварительный просмотр не работает, я буду рад, если бы смог отредактировать этот ответ, чтобы исправить это.
Использование
<com.gazman.WrapContentDraweeView
android:id="@+id/myImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fresco:placeholderImage="@mipmap/myImage"/>
Исходный код
public class WrapContentDraweeView extends SimpleDraweeView {
private int outWidth;
private int outHeight;
public WrapContentDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
super(context, hierarchy);
}
public WrapContentDraweeView(Context context) {
super(context);
}
public WrapContentDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
public WrapContentDraweeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs == null) {
return;
}
TypedArray gdhAttrs = context.obtainStyledAttributes(
attrs,
R.styleable.GenericDraweeView);
try {
int placeholderId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_placeholderImage,
0);
if(placeholderId != 0){
if(isInEditMode()){
setImageResource(placeholderId);
}
else {
loadSize(placeholderId, context.getResources());
}
}
} finally {
gdhAttrs.recycle();
}
}
private void loadSize(int placeholderId, Resources resources) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(resources, placeholderId, options);
outWidth = options.outWidth;
outHeight = options.outHeight;
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
params.width = outWidth;
params.height = outHeight;
super.setLayoutParams(params);
}
}
Ответ 4
В Kotlin вы можете попробовать что-то вроде этого:
val listener = object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
super.onFinalImageSet(id, imageInfo, animatable)
itemView.draweeGif.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
itemView.draweeGif.aspectRatio = (imageInfo?.width?.toFloat() ?: 0.toFloat()) / (imageInfo?.height?.toFloat() ?: 0.toFloat())
}
}
val controller = Fresco.newDraweeControllerBuilder()
.setUri(uriGif)
.setControllerListener(listener)
.setAutoPlayAnimations(true)
.build()
itemView.draweeGif.controller = controller
Для меня это было решением в моем RecyclerView, потому что я искал, чтобы установить layoutParams непосредственно в моем ViewHolder.