Android 动态地将视图膨胀为listView项。古怪的行为

Android 动态地将视图膨胀为listView项。古怪的行为,android,listview,adapter,Android,Listview,Adapter,因此,我将根据一个listView项目中需要的视图数量动态创建视图。当用户单击listView项目时,我展开该项目以显示我创建的膨胀视图。我必须这样做的原因是,膨胀视图的数量需要是动态的。可能有2、3甚至5+ 通货膨胀发生得很好,视野开阔得很。问题是当我在listView中滚动时。它似乎将视图膨胀到其他listview项目,而不是用户单击的项目。我知道这是ListView重用其视图以节省内存的预期行为,但在我的代码中这样做有什么原因吗 为了提供一些背景知识,这个类是一个自定义视图,我将它作为Re

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

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

为了提供一些背景知识,这个类是一个自定义视图,我将它作为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<>();
}

您应该在listview的方法中应用onClick逻辑,因为它具有
OnItemClickListener
/
OnItemSelectedListener
。由于元素是循环使用的,所以onclick可能应用于实际元素,而不是列表的相对项

此处提供了如何使用ListView的完整示例:

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


但是,您应该研究如何使用创建列表。同样的想法也适用,但它在显示列表时更有效,并且为您做了很多工作。

我已经尝试了两种方法。它的工作原理是一样的。我正在使用的ListView是一个ListFragment,我已经为它覆盖了onListItemClick。同样的效果。如果用户单击列表中的第一项,则会将视图膨胀到该项中。但是如果你滚动到第五/第六个项目,(回收),那么效果基本上是它将视图膨胀到该项目以及第一个项目中。有时当我向上滚动到顶部时,视图会切换其膨胀的位置。您的类是添加到listView还是父布局?我看到您正在调用父addView。您可能只需要创建一个列表视图,并使用自定义适配器来生成表单和处理加载等。我无法使用适配器的原因是,每个listview项所需的膨胀视图量可能会发生变化。可能是3或10。无法执行listView getItemViewType。我将视图添加到父布局。因此,每个listview项都有一个称为surveyView的不可见视图。然后,当用户单击listview项时,surveyView变为可见。然后膨胀正确数量的视图。在这种情况下,可扩展列表视图不是更好吗?它内置了对扩展的支持,您可以根据需要扩展子条目。我完全忘记了可扩展列表视图。非常感谢。我要试一试。
@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;
}