【问题标题】:Updating buttons in a ListView更新 ListView 中的按钮
【发布时间】:2013-06-01 11:52:20
【问题描述】:

我想更新ListView 中的按钮。我目前拥有的代码工作正常,但有一个小故障,当到达最后一项时,它会突然用上一篇文章中的错误数据更新第一项,因为它是最后一篇文章。我不知道会发生什么,在我的日志我没有得到任何表明第一项正在更新的信息。 我从similar question 得到了这个代码和想法。

这是我使用的代码:

/**
     * Updates the like/dislike button states 
     */
    public void updateButtons() {
        ListView lv = ((ListView) findViewById(R.id.post_list));
        Log.d("Child Count: ", Integer.toString(lv.getCount()));
        int firstVisible;
        int child;
        for(int i=0; i < lv.getCount(); i++) {
            firstVisible = lv.getFirstVisiblePosition() - lv.getHeaderViewsCount();
            child = i - firstVisible;
            if(child < 0 || child >= lv.getChildCount()) {
                continue;
            }
            if(updated.contains(i)) continue;
            Log.d("Debug", "Updating child:" + Integer.toString(child));
            LinearLayout row = (LinearLayout) lv.getChildAt(child);
            if(likeable.get(i) == 0) {
                LinearLayout btn = (LinearLayout) row.findViewById(R.id.btn_like);
                btn.setClickable(false);
                ImageView imgView = (ImageView) row.findViewById(R.id.img_like);
                imgView.setImageDrawable(getResources().getDrawable(R.drawable.ic_like_selected));
                TextView txtView = (TextView) row.findViewById(R.id.text_like);
                txtView.setTextColor(Color.parseColor("#60007c"));
            }
            if(dislikeable.get(i) == 0) {
                LinearLayout btn = (LinearLayout) row.findViewById(R.id.btn_dislike);
                btn.setClickable(false);
                ImageView imgView = (ImageView) row.findViewById(R.id.img_dislike);
                imgView.setImageDrawable(getResources().getDrawable(R.drawable.ic_dislike_selected));
                TextView txtView = (TextView) row.findViewById(R.id.text_dislike);
                txtView.setTextColor(Color.parseColor("#60007c"));
            }
            Log.d("Debug", "Adding child" + Integer.toString(i) + "TO the updated list");
            updated.add(i);
        }
    }

每次用户滚动列表视图时,我都会运行此代码:

ListView lv = ((ListView) findViewById(R.id.post_list));
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        // TODO Auto-generated method stub
        updateButtons();
    }
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        // TODO Auto-generated method stub
        updateButtons();
    }
});

【问题讨论】:

    标签: java android android-listview


    【解决方案1】:

    目前还不是很清楚是什么问题。当您通过滚动到达最后一项时,第一项(来自适配器的一项或第一个可见的)再次更新?

    我个人的看法是,您以错误的方式处理此问题。从问题来看,您似乎想更新ListView 每一行中的一些按钮。您应该通过更新适配器中的数据并调用notifyDataSetChanged() 而不是使用OnScrollListener 来做到这一点。这对用户操作(喜欢/不喜欢的项目)是有意义的,我怀疑你在用户滚动时创建了一个非常尴尬的喜欢/不喜欢系统。

    此外,如果您只想触摸可见行,则使用 lv.getCount() 遍历所有适配器项是没有意义的(使用您当前执行的代码,您不妨在一个适配器中进行更新去打电话notifyDatasetChanged())。使用getFirstVisiblePosition()getLastVisiblePosition()。您可以通过不调用 updateButtons() 方法来优化代码,除非由于滚动而在屏幕上出现了新行,您可以从 onScroll() 方法的参数中观察/计算(我看到了 updated包含已更新项目的列表?!)。

    【讨论】:

    • 谢谢回答,我的意思是适配器上的第一项。我没有使用SimpleAdapter 的自定义适配器。我只是从服务器获取一个 json 字符串,对其进行解析并确定是否有人已经喜欢/不喜欢特定的帖子,并基于它向用户显示按钮。这只需要在第一次获得帖子后执行一次,然后按钮不会更改。当所有帖子都在屏幕上时它正在工作(预计可以工作)但是当帖子更多时它就出错了。
    • 当我到达最后一项时,列表中的第一项(适配器)会更新(第一项永远不会出现在屏幕上。我怀疑它是如何更新的)。问题是它更新了错误的。 (它会根据上一篇文章的信息进行更新)
    • 并且更新的列表包含已经更新的行,因此我们不需要再次更新它们。 (性能)。我制作了列表以防止第一项再次更新,但它会更新。
    • @MiroMarkarian 在从 json 文件获取/解析列表之后,如果它没有改变,那么简单地更新列表不是更容易吗?
    • 问题是我没有更新列表。我用列表中的数据更新按钮。
    【解决方案2】:

    试试这个代码。对我来说效果很好。

    您的适配器类将如下所示。

    package com.rajesh.getselecteditem;
    import java.util.ArrayList;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.CheckBox;
    import android.widget.CompoundButton;
    import android.widget.CompoundButton.OnCheckedChangeListener;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class ListAdapter extends BaseAdapter {
        Context ctx;
        LayoutInflater lInflater;
        ArrayList<Position> arraylist;
    
        ListAdapter(Context context, ArrayList<Position> products) {
            ctx = context;
            arraylist = products;
            lInflater = (LayoutInflater) ctx
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
    
        @Override
        public int getCount() {
            return arraylist.size();
        }
    
        @Override
        public Object getItem(int position) {
            return arraylist.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;
            if (view == null) {
                view = lInflater.inflate(R.layout.item, parent, false);
            }
    
            Position pos = getselectedposition(position);
            ((TextView) view.findViewById(R.id.Textview1)).setText(""+pos.position);
    
            final ImageView imageView1 = (ImageView) view.findViewById(R.id.imageView1);
    
            CheckBox chkbox = (CheckBox) view.findViewById(R.id.cbBox);
    
            chkbox.setTag(position);
            chkbox.setChecked(pos.ischeckedflag);
            imageView1.setTag(position);
    
    
    
            chkbox.setOnCheckedChangeListener( new OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                    getselectedposition((Integer) buttonView.getTag()).ischeckedflag = isChecked;
                    if(isChecked)
                    {
                        imageView1.setVisibility(View.GONE);
                    }
                    else if(!isChecked)
                    {
                        imageView1.setVisibility(View.VISIBLE);
                    }
                }
            });
    
    
            return view;
        }
    
        Position getselectedposition(int position) {
            return ((Position) getItem(position));
        }
    
        ArrayList<Position> getcheckedposition() {
            ArrayList<Position> checkedposition = new ArrayList<Position>();
            for (Position p : arraylist) {
                if (p.ischeckedflag)
                    checkedposition.add(p);
            }
            return checkedposition;
        }
    
    
    }
    

    您的 Activity 类似于下面的课程

    package com.rajesh.getselecteditem;
    import java.util.ArrayList;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.CheckBox;
    import android.widget.LinearLayout;
    import android.widget.ListView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        ArrayList<Position> listitems = new ArrayList<Position>();
        ListAdapter listAdapter;
        ListView lvMain ;
    
          /** Called when the activity is first created. */
          public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
             lvMain = (ListView) findViewById(R.id.listview);
    
    
    
            arraylistvalueadding();
            listAdapter = new ListAdapter(this, listitems);
    
    
            lvMain.setAdapter(listAdapter);
          }
    
          void arraylistvalueadding() {
            for (int i = 1; i <= 20; i++) {
                listitems.add(new Position(i,false));
            }
          }
    

    }

    您的职位类别在下面。

    public class Position {
          int  position;    
          boolean ischeckedflag;
    
    
          Position(int name, boolean flag) {
              position = name;     
              ischeckedflag = flag;
          }
        }
    

    只需使用列表视图设计您的 main.xml 类。

    您的 listitem.xml 如下所示。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
    
        <CheckBox
            android:id="@+id/cbBox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical" >
        </CheckBox>
    
        <LinearLayout
            android:id="@+id/linearLayout1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:orientation="vertical"
            android:layout_weight="1" >
    
            <ImageView
                android:id="@+id/imageView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_launcher" />
    
            <TextView
                android:id="@+id/Textview1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:text=""
                android:textSize="20sp" >
            </TextView>       
        </LinearLayout>
    
    </LinearLayout>
    

    【讨论】:

      【解决方案3】:

      好的,我自己解决了这个问题。问题不在代码中,也不是因为我的软件。这件事是我发现的一个可能的 android 错误。 :) 我必须再次明确设置数据,即使它是默认的。此代码有效:

      if(likeable.get(i) == 0) {
          LinearLayout btn = (LinearLayout) row.findViewById(R.id.btn_like);
          btn.setClickable(false);
          ImageView imgView = (ImageView) row.findViewById(R.id.img_like);
          imgView.setImageDrawable(getResources().getDrawable(R.drawable.ic_like_selected));
          TextView txtView = (TextView) row.findViewById(R.id.text_like);
          txtView.setTextColor(Color.parseColor("#60007c"));
      } else {
          LinearLayout btn = (LinearLayout) row.findViewById(R.id.btn_like);
          btn.setClickable(true);
          ImageView imgView = (ImageView) row.findViewById(R.id.img_like);
          imgView.setImageDrawable(getResources().getDrawable(R.drawable.ic_like));
          TextView txtView = (TextView) row.findViewById(R.id.text_like);
          txtView.setTextColor(Color.parseColor("#555555"));
      }
      if(dislikeable.get(i) == 0) {
          LinearLayout btn = (LinearLayout) row.findViewById(R.id.btn_dislike);
          btn.setClickable(false);
          ImageView imgView = (ImageView) row.findViewById(R.id.img_dislike);
          imgView.setImageDrawable(getResources().getDrawable(R.drawable.ic_dislike_selected));
          TextView txtView = (TextView) row.findViewById(R.id.text_dislike);
          txtView.setTextColor(Color.parseColor("#60007c"));
      } else {
          LinearLayout btn = (LinearLayout) row.findViewById(R.id.btn_dislike);
          btn.setClickable(true);
          ImageView imgView = (ImageView) row.findViewById(R.id.img_dislike);
          imgView.setImageDrawable(getResources().getDrawable(R.drawable.ic_dislike));
          TextView txtView = (TextView) row.findViewById(R.id.text_dislike);
          txtView.setTextColor(Color.parseColor("#555555"));
      }
      

      为了确切地知道发生了什么,我尽可能多地描述它。 我在上面代码的else 部分设置的属性正是默认情况下在行上设置的属性(使用布局)。问题是当if 不正确时(我们不需要进行任何更改),我们只是跳过它们。当滚动列表时,他们被 android 覆盖(这是错误)。因此,我在代码(else 部分)中明确将它们恢复为默认值,代码按预期工作。

      感谢大家的回答。

      【讨论】:

      • 这不是错误,ListView 将在您上下滚动时回收行,您应该始终为对行所做的任何更改提供默认值。然而,这并不能解释为什么它只发生在第一行。
      • @Luksprog 它发生在第一行,因为我只有 6 个帖子。当滚动到最新的(因为最新的太长)时,它覆盖了我的所有屏幕,所以孩子 0 变成了第 6 号帖子。当滚动到第一个帖子时,它的设置与第 6 个帖子相同。如果帖子更多,其他帖子也会发生。
      • 但是那太糟糕了,我必须不断更新按钮。太多无用的过程了。
      • @Luksprog 天哪,这真的很奇怪。我写了一个新的适配器,第一个条目和最后一个一样!!!!甚至是文本和数据。我的代码中肯定缺少某些东西...
      • 我看不到你的整个代码,我无能为力。但正如我在回答中已经说过的那样,我建议你重新思考你做事的方式。
      猜你喜欢
      • 1970-01-01
      • 2018-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      • 2021-09-16
      • 1970-01-01
      • 2011-03-04
      相关资源
      最近更新 更多