【问题标题】:dynamically inflating views into listView items. odd behaviour动态地将视图膨胀到 listView 项中。奇怪的行为
【发布时间】:2015-06-09 04:44:01
【问题描述】:

所以我根据需要在 listView 项目中的数量动态创建视图。当用户单击 listView 项目时,我展开该项目以显示我制作的膨胀视图。我必须这样做的原因是因为膨胀视图的数量需要是动态的。可能有 2 个、3 个,甚至 5 个以上。

通货膨胀发生得很好,视野扩大得很好。问题是当我在我的 listView 中滚动时。它似乎将视图膨胀到其他列表视图项目,而不是用户单击的项目。我知道这是预期的行为,因为 listViews 重用它们的视图来节省内存,但是它在我的代码中这样做有什么原因吗?

为了提供一些背景故事,这个类是一个自定义视图,我将它作为 RelativeLayout 的元素放入另一个 xml 文件中。 setLayout 函数应该根据需要膨胀尽可能多的视图。 (这是用于轮询功能) 我的适配器很可能是问题所在。

public class SurveyView extends LinearLayout {
private LinearLayout pollContainer;
private Context context;
private String type;
private int numOfAnswers;
private ListView answersList;
private ArrayList<String> answers;
private boolean visibility = true;
private OnClickListener listener;
private ArrayList<View> options;
private int tag = 888888888;

/**
 *
 * @param context the context of the activity
 * @param type the type of poll
 * @param numOfAnswers if the poll is multiple choice (most likely) provide number of answers.
 */
public void setLayout(Context context, String type, int numOfAnswers) {
    this.type = type;
    this.numOfAnswers = numOfAnswers;
    this.context = context;

    switch (type) {
        case "Multiple":
            if (visibility) {
                for (int i = 0; i < numOfAnswers; i++) {
                    View v = LayoutInflater.from(getContext()).inflate(R.layout.poll_multiple_choice_answers_row, null);
                    v.setTag(tag);
                    tag++;
                    v.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(getContext(), v.getTag().toString(), Toast.LENGTH_SHORT).show();
                            RadioButton rb = (RadioButton)v.findViewById(R.id.answer_voted_button);
                            rb.setChecked(true);
                        }
                    });
                    addView(v);
                    options.add(v);
                }
            }
            break;
        case "Slider":
            break;
        case "Tree":
            break;
        case "Sentiment":
            break;
    }
}

public SurveyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setOrientation(VERTICAL);
    options = new ArrayList<>();
}

这是我的适配器代码。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder viewHolder;
    if (convertView == null) {
        viewHolder = new ViewHolder();
        convertView = inflater.inflate(R.layout.polls_card_layout, null);
        viewHolder.type = (TextView)convertView.findViewById(R.id.card_type);
        viewHolder.time = (TextView)convertView.findViewById(R.id.card_poll_time);
        viewHolder.text = (TextView)convertView.findViewById(R.id.card_text);
        viewHolder.space = (TextView)convertView.findViewById(R.id.card_space);
        viewHolder.pollSpace = (TextView)convertView.findViewById(R.id.poll_space);
        viewHolder.type_icon = (ImageView)convertView.findViewById(R.id.card_icon);
        viewHolder.answerView = (SurveyView)convertView.findViewById(R.id.poll_component);
        convertView.setTag(viewHolder);
    }
    else {
        viewHolder = (ViewHolder)convertView.getTag();
    }

    viewHolder.type.setText(data.get(position).getType());
    viewHolder.time.setText(data.get(position).getTime());
    viewHolder.text.setText(data.get(position).getText());

    convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (viewHolder.getAnswerView().getHeight() == 0) {
                viewHolder.answerView.setLayout(context, "Multiple", 5);
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
                params.addRule(RelativeLayout.BELOW, R.id.poll_space);
                params.addRule(RelativeLayout.RIGHT_OF, R.id.card_icon);
                viewHolder.answerView.setLayoutParams(params);
            } else {
                viewHolder.getAnswerView().setVisibility(false);
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, 0);
                params.addRule(RelativeLayout.BELOW, R.id.poll_space);
                params.addRule(RelativeLayout.RIGHT_OF, R.id.card_icon);
                viewHolder.answerView.setLayoutParams(params);
            }
        }
    });
    return convertView;
}

【问题讨论】:

    标签: android listview adapter


    【解决方案1】:

    您应该在列表视图的方法中应用您的 onClick 逻辑,因为它具有 OnItemClickListener/OnItemSelectedListener。由于元素被回收,您的 onclick 可能适用于实际元素而不是列表的相对项目。

    此处提供了如何使用 ListView 的完整示例: https://developer.android.com/guide/topics/ui/layout/listview.html

    但基本思想是扩展 OnItemClick 方法,该方法接收列表、选择的视图(实际使用的视图)和项目的 id。使用列表,您可以获得存储的数据和任何相关数据。

    但是,您应该考虑使用 RecyclerView 创建列表。同样的想法也适用,但它更有效地显示列表并为您完成大量工作。

    【讨论】:

    • 两种方法我都试过了。它的运作方式相同。我正在使用的 ListView 是一个 ListFragment,我已经为它覆盖了 onListItemClick。这是一样的效果。如果用户单击列表中的第一个项目,它会将视图膨胀到该项目中。但是,如果您滚动到第 5/6 个项目,(已回收)那么效果基本上是将视图膨胀到该项目以及第一个项目中。有时当我向上滚动到顶部时,视图会切换它们的膨胀位置..
    • 你的类是添加到 listView 还是父布局?我看到你调用父 addView。您可能只需创建一个列表视图并使用自定义适配器来生成您的表单并处理加载等。
    • 我不能使用适配器的原因是每个列表视图项所需的膨胀视图数量可能会改变。可能是 3 或 10。不能做 listView getItemViewType。我将视图添加到父布局。所以每个列表视图项都有一个称为surveyView 的不可见视图。然后当用户单击 listview 项目时,surveyView 变得可见。然后增加正确的观看次数。
    • 在这种情况下,可扩展的列表视图不是更好吗?它内置了对扩展的支持,您可以根据需要扩展子条目。
    • 我完全忘记了可扩展列表视图。谢谢!我会试一试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多