Android 仅将Recyclerview的第一个位置设置为标题布局

Android 仅将Recyclerview的第一个位置设置为标题布局,android,android-recyclerview,Android,Android Recyclerview,我正在尝试在recyclerview中创建自己的标题布局,而不使用任何库。我已经创建了这两个布局,但现在我不知道如何将第一个位置设置为标题,而其他位置则围绕它滚动 以下是我的标题布局XML: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/shareLa

我正在尝试在recyclerview中创建自己的标题布局,而不使用任何库。我已经创建了这两个布局,但现在我不知道如何将第一个位置设置为标题,而其他位置则围绕它滚动

以下是我的标题布局XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/shareLayout"
android:layout_width="185dp"
android:layout_height="135dp"
android:layout_below="@id/trendingToolbar"
android:background="@color/black">

<ImageView
    android:id="@+id/cameraShareIV"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="10dp"
    app:srcCompat="@drawable/camera_white" />

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/cameraShareIV"
    android:layout_centerHorizontal="true">

    <TextView
        android:id="@+id/infoTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="20dp"
        android:gravity="center_horizontal"
        android:text="@string/share_pic_video"
        android:textColor="@android:color/white"
        android:textSize="13sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/infoTxt"
        android:layout_marginLeft="16dp"
        android:text="@string/share_timeout_txt"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="11sp"
        android:textStyle="bold" />

</RelativeLayout>
以下是我的适配器代码:

public class TrendingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private static final String TAG = TrendingAdapter.class.getSimpleName();

private Context context;
private List<Trending> itemList;
private List<TestTrends> trendsList;

private static final int HEADER = 0;
private static final int ITEMS = 1;

public TrendingAdapter(Context context, List<TestTrends> trendsList) {
    this.context = context;
    this.trendsList = trendsList;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v;
    switch (viewType){
        case HEADER:
           v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_header, parent, false);
           return new TrendingHeaderViewHolder(v);
        case ITEMS:
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_items_layout, parent, false);
            return new TrendingItemsViewHolder(v);
    }
    return null;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    Trending tr = itemList.get(position);
    if (holder instanceof TrendingHeaderViewHolder){
        ((TrendingHeaderViewHolder) holder).cameraShareIV.setOnClickListener( view -> {
            TrendingFragment.newInstance().selectImage();
        });
    } else if (holder instanceof TrendingItemsViewHolder){
        TestTrends tre = trendsList.get(position);
        Picasso.with(context)
                .load(tre.getTestImage())
                .placeholder(R.drawable.default_profile_photo)
                .into(((TrendingItemsViewHolder) holder).testImgView);
    }
}

@Override
public int getItemCount() {
    //return itemList.size();
    return trendsList.size();
}

@Override
public int getItemViewType(int position) {
//        int vType = 0;
//        if (position == 0){
//            vType = 0;
//        }
//        return vType;
    // how do I set only first position to be header
    if (trendsList.get(position) == 0){

    }
}
}
因此,是否有人可以向我解释如何在
getItemViewType()中为常规多视图情况选择正确的视图类型,以及如何将
仅第一个位置设置为标题。

谢谢,我已经添加了完整的Java代码。我是否将适配器设置在正确的位置?

您的目标可以通过在
onBindViewHolder
getItemCount
getItemViewType
方法中进行一些更改来实现:

  • 删除趋势tr=itemList.get(位置)
    onBindViewHolder
    获取,如果holder是
    TrendingItemsViewHolder

    TestTrends tre = trendsList.get(position - 1);
    
  • 将偏移量添加到项目计数大小

    @Override
    public int getItemCount() {
        return trendsList.size() + 1;
    }
    
  • 使您的
    getItemViewType
    始终返回位置0上的标题,否则返回项目

    @Override
    public int getItemViewType(int position) {
        return position == 0 ? HEADER : ITEMS;
    }
    
  • 更新:

    下面是您的适配器在正确单击处理时的外观

     public class TrendingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
        private static final int HEADER = 0;
        private static final int ITEM = 1;
    
        private final List<TestTrends> data;
        private final HeaderClickListener headerClickListener;
    
        public TrendingAdapter(List<TestTrends> data, HeaderClickListener headerClickListener) {
            this.data = data;
            this.headerClickListener = headerClickListener;
        }
    
        @Override
        public int getItemViewType(int position) {
            return position == 0 ? HEADER : ITEM;
        }
    
        @Override
        public int getItemCount() {
            return data.size() + 1;
        }
    
        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View v;
            LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
            switch (viewType){
                case HEADER:
                    v = layoutInflater.inflate(R.layout.trending_header, parent, false);
                    return new HeaderViewHolder(v, headerClickListener);
                default:
                    v = layoutInflater.inflate(R.layout.trending_items_layout, parent, false);
                    return new ItemViewHolder(v);
            }
        }
    
        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
            if (holder.getItemViewType() == ITEM) {
                TestTrends testTrends = trendsList.get(position - 1);
                ((ItemViewHolder)holder).bind(testTrends);
            }
        }
    
        interface HeaderClickListener {
            void onHeaderClicked();
        }
    
        static class HeaderViewHolder extends RecyclerView.ViewHolder {
    
            HeaderViewHolder(View itemView, final HeaderClickListener headerClickListener) {
                super(itemView);
                itemView.setOnClickListener(v -> headerClickListener.onHeaderClicked());
            }
        }
    
        static class ItemViewHolder extends RecyclerView.ViewHolder {
    
            private ImageView testImgView;
    
            ItemViewHolder(View itemView) {
                super(itemView);
                //REPLACE yourId WITH REAL IMAGE VIEW ID
                testImgView = itemView.findViewById(R.id.yourId);
            }
    
            void bind(TestTrends testTrends) {
                Picasso.with(itemView.getContext())
                        .load(testTrends.getTestImage())
                        .placeholder(R.drawable.default_profile_photo)
                        .into(testImgView);
            }
        }
    }
    
    这里是一个实现

    @Override
    public void onHeaderClicked() {
        selectImage()
    }
    
    最后,在创建适配器时,将
    作为
    headerClickListener
    传递

    adapter = new TrendingAdapter(trendsList, this);
    

    您的目标可以通过对
    onBindViewHolder
    getItemCount
    getItemViewType
    方法进行一些更改来实现:

  • 删除趋势tr=itemList.get(位置)
    onBindViewHolder
    获取,如果holder是
    TrendingItemsViewHolder

    TestTrends tre = trendsList.get(position - 1);
    
  • 将偏移量添加到项目计数大小

    @Override
    public int getItemCount() {
        return trendsList.size() + 1;
    }
    
  • 使您的
    getItemViewType
    始终返回位置0上的标题,否则返回项目

    @Override
    public int getItemViewType(int position) {
        return position == 0 ? HEADER : ITEMS;
    }
    
  • 更新:

    下面是您的适配器在正确单击处理时的外观

     public class TrendingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
        private static final int HEADER = 0;
        private static final int ITEM = 1;
    
        private final List<TestTrends> data;
        private final HeaderClickListener headerClickListener;
    
        public TrendingAdapter(List<TestTrends> data, HeaderClickListener headerClickListener) {
            this.data = data;
            this.headerClickListener = headerClickListener;
        }
    
        @Override
        public int getItemViewType(int position) {
            return position == 0 ? HEADER : ITEM;
        }
    
        @Override
        public int getItemCount() {
            return data.size() + 1;
        }
    
        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View v;
            LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
            switch (viewType){
                case HEADER:
                    v = layoutInflater.inflate(R.layout.trending_header, parent, false);
                    return new HeaderViewHolder(v, headerClickListener);
                default:
                    v = layoutInflater.inflate(R.layout.trending_items_layout, parent, false);
                    return new ItemViewHolder(v);
            }
        }
    
        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
            if (holder.getItemViewType() == ITEM) {
                TestTrends testTrends = trendsList.get(position - 1);
                ((ItemViewHolder)holder).bind(testTrends);
            }
        }
    
        interface HeaderClickListener {
            void onHeaderClicked();
        }
    
        static class HeaderViewHolder extends RecyclerView.ViewHolder {
    
            HeaderViewHolder(View itemView, final HeaderClickListener headerClickListener) {
                super(itemView);
                itemView.setOnClickListener(v -> headerClickListener.onHeaderClicked());
            }
        }
    
        static class ItemViewHolder extends RecyclerView.ViewHolder {
    
            private ImageView testImgView;
    
            ItemViewHolder(View itemView) {
                super(itemView);
                //REPLACE yourId WITH REAL IMAGE VIEW ID
                testImgView = itemView.findViewById(R.id.yourId);
            }
    
            void bind(TestTrends testTrends) {
                Picasso.with(itemView.getContext())
                        .load(testTrends.getTestImage())
                        .placeholder(R.drawable.default_profile_photo)
                        .into(testImgView);
            }
        }
    }
    
    这里是一个实现

    @Override
    public void onHeaderClicked() {
        selectImage()
    }
    
    最后,在创建适配器时,将
    作为
    headerClickListener
    传递

    adapter = new TrendingAdapter(trendsList, this);
    

    不行,兄弟。我对问题进行了编辑,以反映我在哪里设置适配器。请看一看奇怪的,我已经仔细检查过了,它对我有效。看起来设置适配器的位置没有问题。请仔细检查,您是否真的接到了onActivityResult呼叫,请求代码为20,结果代码为result_OK,并且您100%调用了setAdapter。因为如果您在RV中没有看到填充的任何内容,可能适配器未设置在allBro,这可能要求太多,但是您可以压缩文件并将其作为驱动器链接发布吗?它现在显示了标题。但当点击时,应用程序崩溃,指向StartActivityForresult热线。关于被附加到某个活动,你知道如何修复吗?@Andromeda似乎你的click listener有错误的实现。避免在
    onBindViewHolder
    中设置click侦听器,并在适配器内部处理单击。最好在ViewHolder的构造函数中设置它,并将带有自定义界面的click事件传递给包含回收器视图的片段/活动。它不起作用。我对问题进行了编辑,以反映我在哪里设置适配器。请看一看奇怪的,我已经仔细检查过了,它对我有效。看起来设置适配器的位置没有问题。请仔细检查,您是否真的接到了onActivityResult呼叫,请求代码为20,结果代码为result_OK,并且您100%调用了setAdapter。因为如果您在RV中没有看到填充的任何内容,可能适配器未设置在allBro,这可能要求太多,但是您可以压缩文件并将其作为驱动器链接发布吗?它现在显示了标题。但当点击时,应用程序崩溃,指向StartActivityForresult热线。关于被附加到某个活动,你知道如何修复吗?@Andromeda似乎你的click listener有错误的实现。避免在
    onBindViewHolder
    中设置click侦听器,并在适配器内部处理单击。最好在ViewHolder的构造函数中设置它,并将带有自定义接口的click事件传递给包含回收器视图的片段/活动。