Android listview 适配器在 getView 中有按钮改变布局

Android listview adapter with buttons in getView that change the layout

我有一个带有几个按钮的列表视图,我想透露更多信息。我有一个 xml 文件用于包含多个嵌套 LinearLayout 的布局。当按下 "Comments" 按钮时,我希望适当的布局出现然后消失。在模型对象内部,我跟踪视图是否被公开。

public View getView(int position, View convertView, ViewGroup parent) {
    final CarmenGrade grade = (CarmenGrade) getItem(position);
    convertView = mInflater.inflate(R.layout.carmen_grade_item, null);
    commentsLayout = (LinearLayout) convertView.findViewById(R.id.commentsLayout);
    commentsButton = (Button) convertView.findViewById(R.id.commentsButton);

    commentsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (grade.isShowingComments() == true) {
                    commentsLayout.setVisibility(View.GONE);
                    grade.setShowingComments(false);
                    /* other similar layout parts cut */
                } else {
                    commentsLayout.setVisibility(View.VISIBLE);
                    grade.setShowingComments(true);
                    /* other similar layout parts cut */
                }
                notifyDataSetChanged();
            }
        });
}

在 Android 4.x 上它在第一次按下时工作并且正确的布局变得可见。再次按下按钮似乎无法始终如一地工作。每隔一段时间它就会消失。

在 Android 5.0 上我收到了很多警告,尽管它似乎大部分时间都有效:

W/View﹕ requestLayout() improperly called by android.widget.TextView{2d2581cb V.ED.... ......ID 0,57-231,114 #7f0a0086 app:id/weightedValueTextView} during layout: running second layout pass

所以我的问题是 - 我如何使用列表中的项目来更改 getView 中的布局,以便它始终如一地工作并且不会抛出错误?我是否错过了一个不同的、非常明显的模式?

编辑 抱歉,忘记放在我初始化评论布局的地方了。绝对有。

在Adapter中,getView()函数被多次调用。因此,当您在侦听器中找到 carmen_grade_item 的某些视图时,它会 return 您最后启动的对象(它的意思可能指向列表视图中其他行的相同对象)。

所以要克服这个问题:

如果你想在你的适配器中使用它class:将特定行的 viewHolder 维护到数组中。或找到特定的布局,例如 clickedView.getParent().findViewById(R.id.someLayout);然后执行你的操作。

所以你的监听器看起来像这样

    commentsButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                        LinearLayout layout=(LinearLayout) ((MainParent which contains child)
v.getParent()).findViewById(R.id.commentsLayout);

                        if(layout.isShown()){
                            layout.setVisibility(View.GONE);
                        }else{
                            layout.setVisibility(View.VISIBLE);
                        }


                    notifyDataSetChanged();
                }
            });

无需使用布尔变量,如下所示。

 if (commentsLayout.isShown()) {
       commentsLayout.setVisibility(View.GONE);
 } else {
        commentsLayout.setVisibility(View.VISIBLE);
 }