英文:
ListView add columns programmatically
问题
我正在创建一个投票应用,其中投票者数量未知。当我知道投票者数量时,我想向ListView添加列。这里有一个示例图片:
有没有一种方法可以动态地向ListView添加列?我已经在过去的2小时里进行了搜索,似乎找不到任何解决办法。
我已经实现了垂直和水平滚动,并且能够在顶部添加投票者姓名,但我无法动态添加投票点数,因为它们位于ListView内部。
以下是我尝试过的方法:
- 填充ListView的布局以添加项目(出于某种原因,例如如果我添加了“0”,它会将“0000”添加到第一行,将“00”添加到其他行)
- 使用RecyclerView(它比ListView效果更好,它可以正确地添加“0”,但由于某种原因宽度不正确)
英文:
I am creating a voting app, which has unknown amount of voters. I would like to add columns to ListView when I know the amount of voters. Here is an example image:
Is there a way to add columns to ListView dynamically? I have googled this for the past 2 hours and can't seem to find any good solution to this.
I already have vertical and horizontal scrolling working and I am able to add voter names on top, but I can't add vote points dynamically, since they are inside the ListView.
Here's what I have tried:
- Inflate layout for ListView to add items (for some reason if I added for example "0", it added "0000" to the first row and "00" to the rest of the rows)
- Use RecyclerView (it worked better than ListView, it added the "0" correctly, but for some reason the width was not what it was supposed to be
答案1
得分: 0
我终于成功创建了这个,所以我想在这里分享一下。我使用了 RecyclerView 来实现它,但如果有人知道如何使用 ListView 来做,我也乐意使用。可能可以通过在 ListView 中使用视图持有者来实现相同的效果?如果成功的话,我会发布我的结果。
// 用于创建 RecyclerView 的适配器
public class ResultsAdapter extends RecyclerView.Adapter<ResultsAdapter.MyViewHolder> {
private Context context;
private List<ListItem> itemsList;
private ArrayList<Profile> profiles;
public class MyViewHolder extends RecyclerView.ViewHolder {
public View view;
public TextView name, extra, votes;
public TextView[] votePoints;
public MyViewHolder(View view) {
super(view);
this.view = view;
name = view.findViewById(R.id.resultsName);
extra = view.findViewById(R.id.resultsBonus);
votes = view.findViewById(R.id.resultsVotePoints);
votePoints = new TextView[profiles.size()];
}
}
public ResultsAdapter(Context context, List<ListItem> itemsList, ArrayList<Profile> profiles) {
this.itemsList = itemsList;
this.profiles = profiles;
this.context = context;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.result_show_votes_item, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
ListItem item = itemsList.get(position);
holder.name.setText(item.getName());
holder.extra.setText(String.valueOf(item.getTotal()));
holder.votes.setText(String.valueOf(item.getVotePoints()));
// 将投票点数添加到布局中
LinearLayout layout = holder.view.findViewById(R.id.resultItemLayout);
LayoutInflater inflater = LayoutInflater.from(context);
for (int i = 0; i < profiles.size(); i++) {
ListItem voteItem = itemsList.get(position);
Profile profile = profiles.get(i);
int voteAmount = profile.votePointsOfItem(voteItem);
// 使用 "layout" 和 "false" 作为参数,从 result_voter_points 中获取宽度和高度
TextView vote = (TextView) inflater.inflate(R.layout.result_voter_points, layout, false);
vote.setText(voteAmount == 0 ? "" : String.valueOf(voteAmount));
layout.addView(vote);
holder.votePoints[i] = vote;
}
}
@Override
public int getItemCount() {
return itemsList.size();
}
}
// 将配置文件名称添加到主题中
LinearLayout topicLayout = findViewById(R.id.topicLayout);
for (Profile p : selectedProfiles) {
TextView name = (TextView) getLayoutInflater().inflate(R.layout.result_voter_name, topicLayout, false);
name.setText(p.getName());
topicLayout.addView(name);
}
RecyclerView recyclerView = findViewById(R.id.recycler_view);
ResultsAdapter adapter = new ResultsAdapter(this, selectedList.getItems(), selectedProfiles);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
英文:
I finally managed to create this, so I though that I would share it in here. I used RecyclerView for doing it, but if anyone knows how to do this with ListView I will happily use that instead. It is probably possible to do this same thing by using view holders in ListView? I'll post my results if it works.
// Adapter for creating the RecyclerView
public class ResultsAdapter extends RecyclerView.Adapter<ResultsAdapter.MyViewHolder> {
private Context context;
private List<ListItem> itemsList;
private ArrayList<Profile> profiles;
public class MyViewHolder extends RecyclerView.ViewHolder {
public View view;
public TextView name, extra, votes;
public TextView[] votePoints;
public MyViewHolder(View view) {
super(view);
this.view = view;
name = view.findViewById(R.id.resultsName);
extra = view.findViewById(R.id.resultsBonus);
votes = view.findViewById(R.id.resultsVotePoints);
votePoints = new TextView[profiles.size()];
}
}
public ResultsAdapter(Context context, List<ListItem> itemsList, ArrayList<Profile> profiles) {
this.itemsList = itemsList;
this.profiles = profiles;
this.context = context;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.result_show_votes_item, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
ListItem item = itemsList.get(position);
holder.name.setText(item.getName());
holder.extra.setText(String.valueOf(item.getTotal()));
holder.votes.setText(String.valueOf(item.getVotePoints()));
// Add vote points to layout
LinearLayout layout = holder.view.findViewById(R.id.resultItemLayout);
LayoutInflater inflater = LayoutInflater.from(context);
for (int i = 0; i < profiles.size(); i++) {
ListItem voteItem = itemsList.get(position);
Profile profile = profiles.get(i);
int voteAmount = profile.votePointsOfItem(voteItem);
// Use "layout" and "false" as parameters to get the width and height from result_voter_points
TextView vote = (TextView) inflater.inflate(R.layout.result_voter_points, layout, false);
vote.setText(voteAmount == 0 ? "" : String.valueOf(voteAmount));
layout.addView(vote);
holder.votePoints[i] = vote;
}
}
@Override
public int getItemCount() {
return itemsList.size();
}
}
// Add profile names to topics
LinearLayout topicLayout = findViewById(R.id.topicLayout);
for (Profile p : selectedProfiles) {
TextView name = (TextView) getLayoutInflater().inflate(R.layout.result_voter_name, topicLayout, false);
name.setText(p.getName());
topicLayout.addView(name);
}
RecyclerView recyclerView = findViewById(R.id.recycler_view);
ResultsAdapter adapter = new ResultsAdapter(this, selectedList.getItems(), selectedProfiles);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
答案2
得分: 0
这个问题的回答如下:
我使用了ListView来完成这个任务,以下是解决方案:
// 将个人资料名称添加到主题中
LinearLayout topicLayout = findViewById(R.id.topicLayout);
for (Profile p : selectedProfiles) {
TextView name = (TextView)
getLayoutInflater().inflate(R.layout.result_voter_name, topicLayout, false);
name.setText(p.getName());
topicLayout.addView(name);
}
final ListView list = findViewById(R.id.resultItems);
ListAdapter adapter = new ListAdapter(this, selectedList.getItems(),
selectedProfiles);
list.setAdapter(adapter);
// 列表视图适配器
public class ListAdapter extends BaseAdapter {
private ArrayList<ListItem> listData;
private ArrayList<Profile> profiles;
private LayoutInflater layoutInflater;
public ListAdapter(Context aContext, ArrayList<ListItem> listData, ArrayList<Profile> profiles) {
this.listData = listData;
this.profiles = profiles;
layoutInflater = LayoutInflater.from(aContext);
}
@Override
public int getCount() {
return listData.size();
}
@Override
public Object getItem(int position) {
return listData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.result_show_votes_item, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ListItem item = listData.get(position);
holder.name.setText(item.getName());
holder.extra.setText(String.valueOf(item.getTotal()));
// 遍历投票者并更新他们给定的分数
for (int i = 0; i < profiles.size(); i++) {
Profile profile = profiles.get(i); // 获取个人资料
TextView vote = holder.votePoints[i]; // 获取用于投票分数的TextView
int voteAmount = profile.votePointsOfItem(item); // 获取项目的投票分数
vote.setText(voteAmount == 0 ? "" : String.valueOf(voteAmount));
}
return convertView;
}
/**
* 保存视图数据的类。
*/
class ViewHolder {
View view;
TextView name, extra;
public TextView[] votePoints;
/**
* 存储视图所需的所有数据。
* @param view convertview
*/
public ViewHolder(View view) {
this.view = view;
name = view.findViewById(R.id.resultsName);
extra = view.findViewById(R.id.resultsBonus);
votePoints = new TextView[profiles.size()];
// 将投票分数添加到布局中
LinearLayout layout = view.findViewById(R.id.resultItemLayout);
for (int i = 0; i < profiles.size(); i++) {
// 使用"layout"和"false"作为参数,从result_voter_points获取宽度和高度
TextView vote = (TextView) layoutInflater.inflate(R.layout.result_voter_points, layout, false);
layout.addView(vote);
votePoints[i] = vote;
}
}
}
}
注意:这只是翻译的代码部分,不包括任何额外的内容。
英文:
I managed to do this with the ListView, here is the solution:
// Add profile names to topics
LinearLayout topicLayout = findViewById(R.id.topicLayout);
for (Profile p : selectedProfiles) {
TextView name = (TextView)
getLayoutInflater().inflate(R.layout.result_voter_name,topicLayout, false);
name.setText(p.getName());
topicLayout.addView(name);
}
final ListView list = findViewById(R.id.resultItems);
ListAdapter adapter = new ListAdapter(this, selectedList.getItems(),
selectedProfiles);
list.setAdapter(adapter);
// List View adapter
public class ListAdapter extends BaseAdapter {
private ArrayList<ListItem> listData;
private ArrayList<Profile> profiles;
private LayoutInflater layoutInflater;
public ListAdapter(Context aContext, ArrayList<ListItem> listData, ArrayList<Profile> profiles) {
this.listData = listData;
this.profiles = profiles;
layoutInflater = LayoutInflater.from(aContext);
}
@Override
public int getCount() {
return listData.size();
}
@Override
public Object getItem(int position) {
return listData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.result_show_votes_item, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ListItem item = listData.get(position);
holder.name.setText(item.getName());
holder.extra.setText(String.valueOf(item.getTotal()));
// Loop through voters and update their given points
for (int i = 0; i < profiles.size(); i++) {
Profile profile = profiles.get(i); // Get profile
TextView vote = holder.votePoints[i]; // Get textview for vote point
int voteAmount = profile.votePointsOfItem(item); // Get vote points amount for item
vote.setText(voteAmount == 0 ? "" : String.valueOf(voteAmount));
}
return convertView;
}
/**
* Class for holding view data.
*/
class ViewHolder {
View view;
TextView name, extra;
public TextView[] votePoints;
/**
* Holds all the necessary data for the view.
* @param view convertview
*/
public ViewHolder(View view) {
this.view = view;
name = view.findViewById(R.id.resultsName);
extra = view.findViewById(R.id.resultsBonus);
votePoints = new TextView[profiles.size()];
// Add vote points to layout
LinearLayout layout = view.findViewById(R.id.resultItemLayout);
for (int i = 0; i < profiles.size(); i++) {
// Use "layout" and "false" as parameters to get the width and height from result_voter_points
TextView vote = (TextView) layoutInflater.inflate(R.layout.result_voter_points, layout, false);
layout.addView(vote);
votePoints[i] = vote;
}
}
}
}
专注分享java语言的经验与见解,让所有开发者获益!
评论