如何在Recycler View中为每个项设置不同的高度

8

我想在Recycler View中为每个项目设置不同的高度。通常我们每一行都得到相同的高度。但我需要不同的高度,例如,如果前三行的高度为70,那么我需要剩余的高度为0。我的代码如下。但是它没有正确设置。请建议我进行编辑。

public class MainActivity extends AppCompatActivity {

private RecyclerView rvListProfiles;
private ListProfileAdapter listProfileAdapter;
private String[] list = new String[]{"ABC","DEF","GHI","JKL","MNO"};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    rvListProfiles = findViewById(R.id.rvListProfiles);

    listProfileAdapter = new ListProfileAdapter(list, this);
    RecyclerView.LayoutManager mLayoutManager = new 
    LinearLayoutManager(getApplicationContext());
    rvListProfiles.setLayoutManager(mLayoutManager);
    rvListProfiles.setItemAnimator(new DefaultItemAnimator());
    rvListProfiles.setAdapter(listProfileAdapter);
    String listString = Arrays.toString(list);
    System.out.println("List "+listString);
}
}

项目XML

<?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="70dp"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:background="@android:color/darker_gray"
    android:padding="10dp"
    android:id="@+id/parentLayout">

<ImageView
    android:id="@+id/profileImage"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_alignParentStart="true"
    android:layout_centerVertical="true"
    android:src="@mipmap/love"
    android:transitionName="imageTransition" />

<TextView
    android:id="@+id/profileName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_marginStart="23dp"
    android:layout_toEndOf="@+id/profileImage"
    android:padding="2dp"
    android:text="TextView"
    android:textColor="@android:color/background_light"
    android:textSize="18sp"
    android:transitionName="nameTransition" />

<TextView
    android:id="@+id/profileDesc"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/profileImage"
    android:layout_alignStart="@+id/profileName"
    android:layout_marginTop="5dp"
    android:maxLines="1"
    android:padding="2dp"
    android:text="@string/dummy_data"
    android:textColor="@android:color/background_light"
    android:textSize="12sp"
    android:transitionName="descTransition" />

   </RelativeLayout>

ViewHolder class

public class ListProfileViewHolder extends RecyclerView.ViewHolder {

public ImageView profileImage;
public TextView profileName;
public TextView profileDesc;
public RelativeLayout parentLayout;
public Context context;

public ListProfileViewHolder(View itemView, Context mContext) {
    super(itemView);
    this.context = mContext;
    profileImage = itemView.findViewById(R.id.profileImage);
    profileName = itemView.findViewById(R.id.profileName);
    profileDesc = itemView.findViewById(R.id.profileDesc);
    parentLayout = itemView.findViewById(R.id.parentLayout);
}

}

适配器类
public class ListProfileAdapter extends 
RecyclerView.Adapter<ListProfileViewHolder> {

private String[] list;
private Context mContext;
private int height[] = {70,70,70,
                        0,0,0,0};

public ListProfileAdapter(String[] list, Context mContext) {
    this.list = list;
    this.mContext = mContext;
}

@Override
public ListProfileViewHolder onCreateViewHolder(ViewGroup parent, int 
viewType) {
    View layoutView = 
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, 
null);
    return new ListProfileViewHolder(layoutView, mContext);
}

@Override
public void onBindViewHolder(final ListProfileViewHolder holder, int 
position) {


    holder.parentLayout.setLayoutParams(new 
RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            height[position]));
    holder.profileName.setText(list[position]);
    holder.profileImage.setOnClickListener(new View.OnClickListener() 
{
     @Override
     public void onClick(View view) {
         Intent sharedIntent = new 
Intent(mContext,SharedActivity.class);
         sharedIntent.putExtra("name",holder.profileName.getText());
         sharedIntent.putExtra("desc",holder.profileDesc.getText());
         Pair[] pairs = new Pair[3];
         pairs[0] = new Pair<View,String> 
(holder.profileImage,"imageTransition");
         pairs[1] = new Pair<View,String> 
(holder.profileName,"nameTransition");
         pairs[2] = new Pair<View,String> 
(holder.profileDesc,"descTransition");

         ActivityOptions options = 
ActivityOptions.makeSceneTransitionAnimation((Activity) 
mContext,pairs);
         mContext.startActivity(sharedIntent,options.toBundle());
     }
 });
    holder.parentLayout.setOnClickListener(new View.OnClickListener() 
{
        @Override
        public void onClick(View view) {
            height = new int[]{0,0,0,
                    70,70,70,70,};
            notifyDataSetChanged();
        }
    });
}

@Override
public int getItemCount() {
    return list.length;
}
}

你的代码看起来没问题。有什么问题吗? - Vladyslav Matviienko
https://dev59.com/5FYO5IYBdhLWcg3wTfxv - AskNilesh
@VladyslavMatviienko 的高度为70,在编程时设置可能太小了,无法看清。 - Rahul Surendran
那你为什么要将它设置为70呢? - Vladyslav Matviienko
@VladyslavMatviienko 但它足够大,可以在我们在XML中设置时看到,而无需通过编程设置。 - Rahul Surendran
显示剩余4条评论
5个回答

3
尝试像这样做。
holder.parentLayout.requestLayout();
            if (position == 0 || position==1 || position==2) {
                holder.parentLayout.getLayoutParams().height = height[position];
            } else {
                holder.parentLayout.getLayoutParams().height = height[position];
            }

我们不能将其与位置进行比较,因为在下一步中,当我们点击一个项目时,我们需要更改每个高度。 - Rahul Surendran
你在if和else中添加了相同的代码行,那么if条件语句还有什么用处呢? - Chirag Savsani

1

在.xml文件中,高度以dp为单位(70dp),但在编码中则以像素为单位。

因此,要正确获取大小,需要将dp转换为px,然后通过编程应用它:

将dp转换为px:

public int DpToPx(Activity activity, int dp){
    Resources r  = activity.getResources();
    int px    = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
    return px;

}

然后将其应用于您的布局参数:
holder.parentLayout.setLayoutParams(newRelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
        DPToPx(activity, height[position]));

让我检查一下,先生。 - Rahul Surendran
先生,我们如何在适配器中使用它,因为在适配器中无法访问活动。 - Rahul Surendran
在你的适配器构造函数中设置它:public ListProfileAdapter(String[] list, Context mContext, Activity activity) { this.list = list; this.mContext = mContext; this.activity = activity; } - Alvin Tom
这里您给了我解决方案,节省了我的时间。非常感谢您,先生。 - Rahul Surendran

1
你可以尝试使用StaggeredGridLayoutManager来处理不对称的项目。
尝试更改这个。
RecyclerView.LayoutManager mLayoutManager = new 
    LinearLayoutManager(getApplicationContext());

到这里

RecyclerView.LayoutManager mLayoutManager = new 
    StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);

以下是一些例子:

1:错落有致的GridView

2:错落有致的网格布局


1
在我的情况下,我将视图添加到了FlowLayout中,但是所有项目的高度都相同。
解决方案: 在项目布局xml文件中,只使用RelativeLayout作为根布局,并确保包含动态添加子视图的布局也被RelativeLayout包围。
就像这样:
<RelativeLayout>
  ...
  <FlowLayout />

</RelativeLayout>

0

由于您正在更新布局大小,因此需要刷新UI,请在布局大小更新后尝试调用此行:

holder.parentLayout.requestLayout(); //必须刷新屏幕


让我看看,先生。 - Rahul Surendran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接