RecyclerView项目动态高度微口吃

时间:2016-02-23 23:07:17

标签: performance android-layout android-recyclerview android-adapter android-glide

我使用EndlessAdapterRecyclerView来从服务器获取和加载数百个项目。 Glide负责加载每一行的图像。

如果用户滚动缓慢,一切正常,但是当他晃动时,滚动时会出现一些微观的口吃。 我认为这是因为每行的图像高度不同,但我不知道如何消除它。

我的适配器代码:

public final class ImagesAdapter extends EndlessAdapter<Image, ImagesAdapter.imageHolder> {

@NonNull
private static Fragment mFragment;
private OnItemClickListener onItemClickListener;
private static int  mScreenWidth;
private int layoutStyle;


public ImagesAdapter(@NonNull Fragment fragment, List<Image> images, int layoutStyle) {
    super(fragment.getActivity(), images == null ? new ArrayList<Image>() : images);
    mFragment = fragment;
    setHasStableIds(true);
    mScreenWidth = fragment.getResources().getDisplayMetrics().widthPixels;
    this.layoutStyle = layoutStyle;
}

public void changeLayout(int layoutStyle){
    this.layoutStyle = layoutStyle;
}

public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
    this.onItemClickListener = onItemClickListener;
}

@Override
public long getItemId(int position) {
    return (!isLoadMore(position)) ? mItems.get(position).getId() : -1;
}

@Override
protected imageHolder onCreateItemHolder(ViewGroup parent, int viewType) {
    final imageHolder holder;
    switch (layoutStyle) {
        case 0:
        default:
            holder = new imageHolder(mInflater.inflate(R.layout.item_image_enhanced_optim, parent, false));
            break;
        case 1:
            holder = new imageHolder(mInflater.inflate(R.layout.item_image, parent, false));
            break;
    }
    return holder;
}

@Override
protected ProgressViewHolder onCreateItemProgressBarHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);
    return new ProgressViewHolder(v);
}

@Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
    super.onViewRecycled(holder);
    if (holder instanceof ProgressViewHolder) {
        ((ProgressViewHolder) holder).progressBar.stop();
        Timber.d("Stopped progressbar");
    }
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder.getItemViewType() == VIEW_TYPE_ITEM) {
        ((imageHolder) holder).bind(mItems.get(position));
    } else {
        ((ProgressViewHolder) holder).start();
    }
}

public void shuffle(List<Image> images) {
    mItems.clear();
    this.mItems.addAll(images);
    notifyDataSetChanged();
}

final class imageHolder extends RecyclerView.ViewHolder {

    @Bind(R.id.item_image_content)
    FrameLayout container;
    @Bind(R.id.item_image_img)
    ImageView mImageView;
    @Bind(R.id.item_image_name)
    TextView imageName;
    @Bind(R.id.item_author_name)
    TextView imageAuthorName;
    @Bind(R.id.item_author_image)
    CircleImageView userImage;
    @Bind(R.id.item_image_date)
    TextView imageDate;
    @Bind(R.id.item_image_comments)
    TextView comments;
    @Bind(R.id.item_view_on_map)
    LinearLayout viewOnMap;
    @Bind(R.id.item_view_share)
    LinearLayout share;
    @Bind(R.id.moreView)
    LinearLayout moreView;
    @Bind(R.id.progress_image)
    LoadingView loadingView;

    public imageHolder(View view) {
        super(view);
        ButterKnife.bind(this, view);
    }

    public void bind(@NonNull final Image image) {

        container.setOnClickListener(new onImageClickListener(getAdapterPosition()));
        userImage.setOnClickListener(new onAuthorClickListener(userImage, getAdapterPosition()));
        viewOnMap.setOnClickListener(new onViewOnMapClickListener(getAdapterPosition()));
        share.setOnClickListener(new onShareClickListener(getAdapterPosition()));
        moreView.setOnClickListener(new onMoreClickListener(getAdapterPosition()));
        loadingView.setVisibility(View.VISIBLE);

        imageName.setText(image.getCombinedTitle());
        imageAuthorName.setText(image.getAuthor());
        imageDate.setText(image.getReadableDate());
        comments.setText(image.getComments());


        if(!loadingView.isCircling())
            loadingView.start();
        Glide.with(mFragment)
                .load(image.getImageSrc(mScreenWidth))
                .crossFade()
                .override(mScreenWidth, (int) ((float) mScreenWidth / image.getRatio()))
                .listener(new RequestListener<String, GlideDrawable>() {
                    @Override
                    public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                        loadingView.stop();
                        loadingView.setVisibility(View.GONE);


                        return false;
                    }
                })
                .into(mImageView);

    }


}

和行项目

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_container"
    android:layout_marginBottom="5dp"
    android:layout_marginLeft="0dp"
    android:layout_marginRight="0dp"
    android:layout_marginTop="5dp"
    app:cardCornerRadius="0dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/white">

    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/light_gray"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/item_image_img"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            tools:src="@drawable/header"
            android:contentDescription="@string/img_content"
            android:scaleType="fitXY" />

        <FrameLayout
            android:id="@+id/item_image_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clickable="true"
            android:foreground="?selectableItemBackgroundBorderless"
            android:orientation="vertical" />

    </FrameLayout>

    <include layout="@layout/item_image_header"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:gravity="center_vertical"
        android:layout_marginLeft="47dp"
        android:visibility="visible"
        android:paddingRight="10dp"
        android:layout_marginBottom="5dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            tools:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:paddingBottom="5dp"
            android:paddingTop="5dp"
            android:gravity="center_vertical">

            <ImageView
                android:layout_width="10dp"
                android:layout_height="10dp"
                android:layout_marginRight="3dp"
                android:contentDescription="@string/descr" />

            <TextView
                android:id="@+id/item_image_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:textColor="@color/colorPrimary"
                android:textSize="15.0sp"
                android:layout_gravity="center_vertical" />

        </LinearLayout>


        <TextView
            android:id="@+id/item_image_comments"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:ellipsize="end"
            android:maxLines="4"
            tools:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:textColor="@android:color/primary_text_light_nodisable"
            android:textSize="13.0sp"
            android:layout_marginBottom="10dp" />



    </LinearLayout>

    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:background="@drawable/divider_shape"
        android:layout_height="0.5dp" />

    <include layout="@layout/item_image_bottom_buttons"/>


</LinearLayout>

1 个答案:

答案 0 :(得分:1)

滑行停止加载图像当您快速滚动列表时,它可以提高滚动速度并避免任何抖动

如果您想向用户展示图片,我建议您使用Picasso。 https://github.com/square/picasso

然而,毕加索并不擅长缓存图像或缓存有限

或者使用placeHolder来表示图像。

修改

抬头你可以用Glide轻松完成

Glide.with(getActivity())
                .load("http://www.mediafile.com/12364f")
                .placeholder(R.drawable.circle_placeholder_drawable)//this will show this image till your image is not fully loaded
                .error(R.drawable.error_drawable)// if there is a problem in loading image an error image would be loaded instead
                .into(holder.mFileTransferCircleImageView);