【问题标题】:Gaps and unexpcted moves in RecyclerViewRecyclerView 中的差距和意外移动
【发布时间】:2015-09-09 13:32:45
【问题描述】:

我使用RecyclerViewStaggeredGridLayoutManager 来显示外观略有不同的项目。在我使用 JakeWharton (link) 的 AspectRatioImageView 的项目中,在 Picasso 实际下载和显示图像之前保持 imageView 的大小。 RV(RecyclerView)由无限滚动模式的服务器数据填充。

问题是(如图所示),scolling时,RV顶部和底部出现一些间隙(在图片中,有时项目在列之间移动!(截图很难: D)

编辑 2: 我忘记了一件非常重要的事情,我对所有项目使用相同的布局,但关于适配器项目 某些部分布局将它们的可见性更改为 @ 987654330@,反之亦然

我的问题: 为什么 RV 会这样?难道我做错了什么?这在 RV 中正常吗?

代码很大,不知道放在这里哪个部分有用。如果你能缩小原因,我会在这里放一些代码。


编辑:与问题相关的代码部分

xml:

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_texture"
    android:padding="@dimen/padding_lvlhalf"
    android:scrollbarStyle="outsideOverlay"/>

初始化视图:

@Bind(R.id.recycler_view) RecyclerView mRecyclerView;
.
.
.
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(columnCount, direction));
mRecyclerView.setAdapter(
    new RecyclerViewAdapter<>(ctx, new ViewFiller<Post, DashboardPostViewHolder>() {
        @Override
        public void fill(Post post, DashboardPostViewHolder holder) {
            holder.fill(post);
        }

        @Override
        public DashboardPostViewHolder getViewHolder(View view) {
            return new DashboardPostViewHolder(view, receiverName);
        }

        @Override
        public int getLayoutID() {
            return R.layout.post_dashboard;
        }

    });)

我的自定义适配器:

    public RecyclerViewAdapter(Context context, ViewFiller filler) {
    super();
    this.filler = filler;
    mLayoutInflater = LayoutInflater.from(context);
    items = new ArrayList<>();
}

@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent,
                                         int viewType) {
    View v = mLayoutInflater.inflate(filler.getLayoutID(), parent, false);
    return filler.getViewHolder(v);
}

@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
    filler.fill(getItem(position), holder);
}

@Override
public int getItemCount() {
    return items.size();
}

@Override
public long getItemId(int position) {
    return position;
}

public T getItem(int position){
    return items.get(position);
}

public void addItem(int position, T item){
    items.add(position, item);
    notifyItemInserted(position);
}

public void addItem(T item){
    items.add(item);
    notifyItemInserted(items.size() - 1);
}

public void addItems(List<T> data){
    int oldSize = items.size();
    items.addAll(data);
    notifyItemRangeInserted(oldSize, data.size());
}

public void addItemsToListHead(List<T> data){
    items.addAll(0, data);
    notifyItemRangeInserted(0, data.size());
}

public void resetData(List<T> data) {
    this.items = data;
    notifyDataSetChanged();
}

public void removeItem(int position){
    items.remove(position);
    notifyItemRemoved(position);
}

public void clear(){
    this.items.clear();
    notifyDataSetChanged();
}

public List<T> getItems(){
    return items;
}

ViewFiller接口

public interface ViewFiller<D, VH extends BaseViewHolder>{
    void fill(D data, VH holder);

    VH getViewHolder(View view);

    @LayoutRes int getLayoutID();
}

编辑 2(续):我的项目 xml 以及我如何填充它们..

    <android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="@dimen/margin_lvlhalf"
    app:cardUseCompatPadding="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/post"
        android:background="@color/poinila_background">


        <TextView
            android:layout_gravity="right"
            android:text="@string/test_title"
            android:layout_margin="@dimen/margin_lvl1"
            style="@style/match_wrap.large_text.centered_right"
            android:id="@+id/post_title"
            android:visibility="gone"/>

        <!--Post Image-->
        <com.shaya.poinila.android.presentation.view.AspectRatioImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitXY"
            android:contentDescription="@string/post_content_description"
            android:id="@+id/post_image"
            android:visibility="gone"
            app:aspectRatioEnabled="true"
            app:dominantMeasurement="width"
            />

        <!--Content-->
        <TextView
            android:id="@+id/post_content"
            style="@style/match_wrap.medium_text.three_line.end_ellipsize"
            android:layout_margin="@dimen/margin_lvl1"/>
        <!--android:text="@string/test_long"-->

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

        <!--Post Author-->
        <include android:id="@+id/post_author"
            layout="@layout/circle_image_title_subtitle_reverse"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/margin_lvl1"/>

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

        <!--Post Stats (favs, comments, etc) -->
        <include android:id="@+id/post_stats"
            layout="@layout/stats"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/margin_lvlhalf"
            android:layout_marginBottom="@dimen/margin_lvlhalf"/>

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

        <!--Post Collection Info-->
        <include layout="@layout/rounded_image_title_subtitle_reverse"
            android:id="@+id/post_collection"/>

    </LinearLayout>
</android.support.v7.widget.CardView>

PostViewHolder

public class PostViewHolder extends RecyclerView.ViewHolder
    public void fill(Post post) {
        if (post.type == PostType.IMAGE) {
            postImage.setVisibility(View.VISIBLE);
            postName.setVisibility(TextUtils.isEmpty(post.name) ? View.VISIBLE : View.GONE);
            /*if (TextUtils.isEmpty(post.summary))
                postContent.setVisibility(View.GONE);*/
        }else{ //post.type == PostType.TEXT
            postImage.setVisibility(View.GONE);
            postName.setVisibility(View.VISIBLE);
            postContent.setVisibility(View.VISIBLE);
        }
        // contetnt
        if (TextUtils.isEmpty(post.summary) && !TextUtils.isEmpty(post.contentUrl)) {
            DataRepository.getInstance().getPostContent(post.contentUrl, postContent);
        }
        else{
            setText(postContent, post.summary);
        }
    .
    .
    .
    }   
}

抱歉,帖子太长了!

【问题讨论】:

  • 你好.. 你解决了这个问题吗?我也有同样的问题。。谢谢。
  • @GennadiiSaprykin :不完全!但请记住 RV 使用有限数量的子视图并将它们重用于不同的项目(RV 适配器中的对象),因此在onBindView 中,您必须完全初始化(可见性、值、大小、状态等)子视图的部分和子视图从开始。抱歉英语不好,希望我足够清楚!
  • 是的,我想我在onBindViewHolder 中初始化了所有内容,尽管我仍然有差距。不过,这个 hack 对我有用:stackoverflow.com/questions/33126960/… 看起来很丑,但消除了所有的差距。

标签: android-recyclerview


【解决方案1】:
  1. 您可能在项目的根 ViewGroup 中有边距。
  2. manager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);

【讨论】:

  • 感谢您的回复。我没有意识到这一点!你知道造成差距的原因是什么吗?如果它们在 SGV 中是不可避免的,那么 HANDLING_NONE 不是一个坏方法吗?
  • 我照你说的做了,唯一的不同是 RV 不再填补这些空白!差距还在扩大...
  • 将您的布局添加到问题中。
  • 我编辑了这个问题。告诉我是否有任何令人困惑的地方或需要额外的代码。
  • 嘿,你忘了添加项目布局。
【解决方案2】:

这样做,网格项目之间的间距保持不变

private boolean flagDecoration = false;
if(!flagDecoration)
{
    ItemOffsetDecoration itemDecoration = new ItemOffsetDecoration(getContext(),(R.dimen.spacing));
    recyclerView.addItemDecoration(itemDecoration);
    flagDecoration = true;
}

【讨论】:

    猜你喜欢
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多