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

And*_*eda 1 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/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>
Run Code Online (Sandbox Code Playgroud)

该布局包含一个图像视图,目前用作相机按钮。我想从图库中选择图像并围绕这个布局头填充它们。这是项目布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:minHeight="150dp">

<RelativeLayout
    android:layout_width="180dp"
    android:layout_height="wrap_content"
    android:minHeight="140dp">

    <ImageView
        android:id="@+id/trending_imageView"
        android:layout_width="match_parent"
        android:layout_height="140dp"
        tools:src="@drawable/ic_trophy"
        android:scaleType="fitXY"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="22dp"
        android:layout_below="@id/trending_imageView"
        android:background="@android:color/black"
        android:alpha="0.4"
        android:layout_marginTop="-20dp"
        android:layout_centerVertical="true"
        android:gravity="center_vertical">

        <TextView
            android:id="@+id/trending_userNameTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="Jan Losert"
            android:textSize="14sp"
            android:textColor="@android:color/white"
            android:maxLines="1"
            android:layout_marginLeft="8dp"/>

        <TextView
            android:id="@+id/trending_itemsCountTV"
            android:layout_width="wrap_content"
            android:layout_height="18dp"
            android:background="@drawable/badge_trending"
            tools:text="3"
            android:textColor="@android:color/white"
            android:layout_toRightOf="@id/trending_userNameTV"
            android:layout_marginLeft="16dp"/>

    </RelativeLayout>

</RelativeLayout>

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

和我的模型类如下:

public class TestTrends {

public String testImage;

public TestTrends() {
}

public TestTrends(String testImage) {
    this.testImage = testImage;
}

public String getTestImage() {
    return testImage;
}

public void setTestImage(String testImage) {
    this.testImage = testImage;
}
}
Run Code Online (Sandbox Code Playgroud)

这是我的适配器代码:

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){

    }
}
}
Run Code Online (Sandbox Code Playgroud)

我添加了 like 的部分my activity code and the selectImage() from onBindViewHolder来使这个简短如下:

public class TrendingFragment extends Fragment {

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

private Toolbar trendingToolbar;
private ImageView cameraSharePic;

private RecyclerView trendingRV;
private TrendingAdapter adapter;
private List<TestTrends> trendsList = new ArrayList<>();

public TrendingFragment() {
    // Required empty public constructor
}

public static TrendingFragment newInstance() {
    TrendingFragment tf = new TrendingFragment();
    return tf;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.black));
    View tv = inflater.inflate(R.layout.fragment_trending, container, false);

    initViews(tv);

    ((AppCompatActivity) getActivity()).setSupportActionBar(trendingToolbar);

    trendingToolbar.setTitle(getResources().getString(R.string.trending_title));
    trendingToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
    trendingToolbar.setSubtitle(getResources().getString(R.string.trending_sub_title));
    trendingToolbar.setSubtitleTextColor(getResources().getColor(android.R.color.white));

    trendingRV.setHasFixedSize(true);
    //GridLayoutManager glm = new GridLayoutManager(getActivity(), 3,        GridLayoutManager.VERTICAL, false);
    //trendingRV.setLayoutManager(glm);

    trendingRV.setLayoutManager(new LinearLayoutManager(getActivity()));

    return tv;
}

private void initViews(View tv) {
    trendingToolbar = tv.findViewById(R.id.trendingToolbar);
    trendingRV = tv.findViewById(R.id.trendingRV);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.trending_menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_all_friends:
            Log.d(TAG, "All Friends Selected");
            break;
        case R.id.action_custom:
            Log.d(TAG, "Custom Selected");
            break;
    }
    return super.onOptionsItemSelected(item);
}

public void selectImage() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    getActivity().startActivityForResult(intent, 20);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
        case 20:
            if (resultCode == Activity.RESULT_OK) {
                String im = data.getData().toString();
                TestTrends tr = new TestTrends();
                tr.setTestImage(im);

                trendsList.add(tr);
                adapter = new TrendingAdapter(getActivity(), trendsList);
                trendingRV.setAdapter(adapter);
            }
            break;
    }

}
}
Run Code Online (Sandbox Code Playgroud)

那么有人可以向我解释如何选择正确的视图类型getItemViewType() for general multiple views cases以及如何设置only the first position as header. 谢谢,我已经添加了完整的 Java 代码。我是否将适配器设置在正确的位置?

Yur*_*huk 5

你的目标可以通过一些变化来实现onBindViewHoldergetItemCount并且getItemViewType方法:

  1. 删除Trending tr = itemList.get(position);onBindViewHolder和偏移适用于从集合中获取数据,如果持有人的实例TrendingItemsViewHolder

    TestTrends tre = trendsList.get(position - 1);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 为您的项目计数大小添加一个偏移量

    @Override
    public int getItemCount() {
        return trendsList.size() + 1;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使您getItemViewType始终在位置 0 和 ITEMS 上返回 HEADER 否则。

    @Override
    public int getItemViewType(int position) {
        return position == 0 ? HEADER : ITEMS;
    }
    
    Run Code Online (Sandbox Code Playgroud)

更新:

这是您的适配器在正确点击处理后的样子

 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还应该向片段添加一个接口实现

public class TrendingFragment extends Fragment implements TrendingAdapter.HeaderClickListener
Run Code Online (Sandbox Code Playgroud)

这是一个实现

@Override
public void onHeaderClicked() {
    selectImage()
}
Run Code Online (Sandbox Code Playgroud)

最后通过thisas headerClickListener,在创建适配器时

adapter = new TrendingAdapter(trendsList, this);
Run Code Online (Sandbox Code Playgroud)