2013-06-01 77 views
0

我想更新我的按鈕ListView。我目前的代碼工作正常,但有一個小故障,當到達最後一個項目時,它突然更新第一個項目,因爲它是最後一篇文章中的錯誤數據。我不知道發生了什麼,在我的日誌我什麼都沒有得到,表明第一個項目正在更新。 我從similar question得到了這段代碼和想法。更新ListView中的按鈕

這裏是我使用的代碼:

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

回答

0

好的我自己解決了這個問題。問題不在代碼中,也不在我的軟件中。這件事是我發現一個可能的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覆蓋(這裏是bug)。所以我明確地將它們恢復爲代碼中的默認值(else部分),代碼按假定的方式工作。

感謝所有的答案。

+0

這不是一個錯誤,當您上下滾動時,ListView會循環使用行,您應該始終爲您對行進行的任何更改提供默認值。但這並不能解釋爲什麼它只發生在第一行。 – Luksprog

+0

@Luksprog它發生在第一行,因爲我只有6個帖子。當滾動到最新的一個(因爲最新的一個太長),它覆蓋了我的所有屏幕,所以孩子0成爲帖子號碼6.當滾動到第一帖子時,它具有與第六帖子相同的設置。如果帖子更多,其他帖子也會發生。 –

+0

但是,這太糟糕了,我必須不斷更新按鈕。這太多無用的進程。 –

1

這不是很清楚是什麼問題。當您通過滾動到達最後一個項目時,第一個項目(來自適配器或第一個可見項目)再次更新?

我個人的意見是,你已經走錯了方向。從這個問題看來,你想要更新ListView的每一行中的一些按鈕。您應通過更新適配器中的數據並調用notifyDataSetChanged()而不是使用OnScrollListener來完成此操作。這對用戶操作(喜歡/不喜歡的項目)是有意義的,我懷疑你在用戶滾動上創建了一個非常尷尬的喜歡/不喜歡的系統。

此外,使用lv.getCount()來遍歷所有適配器項目(如果您只想觸及可見行)沒有意義(使用您當前所做的代碼,也可以一次執行適配器中的更新並致電notifyDatasetChanged())。使用getFirstVisiblePosition()getLastVisiblePosition()。您可以通過不調用updateButtons()方法來優化代碼,除非由於滾動而在屏幕上出現新行,您可以從onScroll()方法的參數中觀察/計算(並且我看到一個包含已更新項目的updated列表?!)。

+0

Thx爲答案,我的意思是適配器上的第一項。我沒有使用'SimpleAdapter'的自定義適配器。我只是從服務器獲取json字符串,解析它,並確定是否有人已經喜歡/不喜歡特定的帖子,並基於它,我向用戶顯示按鈕。只有在第一次獲得帖子之後才需要完成這些操作,之後按鈕不會改變。當所有的帖子都在屏幕上(預計會工作),但它在帖子變得更多時出錯。 –

+0

列表中的第一項(適配器)更新時,我到達最後一項(第一項不在屏幕上..我懷疑它是如何更新)..問題是它更新錯誤。 (它更新了最後發佈的信息) –

+0

,更新的列表包含已經更新的行,因此我們不需要再次更新它們。 (用於表演)。我列出了這個清單,以防止第一個項目再次更新,但它會更新。 –

1

試試這段代碼。它爲我工作得很好。

您的適配器類將如下所示。

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>