更新ListView中的按钮

时间:2013-06-01 11:52:21

标签: java android android-listview

我想更新ListView中的按钮。我目前的代码工作正常,但有一个小故障,当到达最后一个项目时,它突然更新第一个项目与上一篇文章中的错误数据,因为它是最后一篇文章。我不知道会发生什么,在我的log我没有得到任何表明第一项正在更新的内容。 我从这个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时都会运行此代码:

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();
    }
});

3 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

尝试使用此代码。它对我来说很好。

您的Adapter类如下所示。

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;
    }


}

您的活动就像下面的课程一样

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>

答案 2 :(得分:0)

好的,我自己解决了这个问题。问题不在代码中,也不在于我的软件。事情是我发现的一个可能的机器人bug。 :)我必须再次显式设置数据,即使它是默认数据。这段代码有效:

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部分)中的默认值,代码按预期工作。

谢谢大家的回答。