2016-07-14 108 views
1

我正在使用listview綁定一些項目,並點擊我想更新listview視圖,但是當我滾動它的效果應用於其他視圖隨機更改位置,如果滾動更多的時間。列表視圖更新隨機滾動

這是我的代碼。

activity_main.xml中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:orientation="vertical"> 
<ListView 
    android:id="@+id/twvTest" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"></ListView> 
</LinearLayout> 

MainActivity.java
public class MainActivity extends Activity { 
ListView twvTest; 
ArrayList<DataModel> dataModels; 
NameListAdapter adapter; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    twvTest = (ListView) findViewById(R.id.twvTest); 

    dataModels = new ArrayList<>(); 
    adapter = new NameListAdapter(MainActivity.this, dataModels); 
    twvTest.setAdapter(adapter); 
    twvTest.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
      for (int i = 0; i < twvTest.getCount(); i++) { 
       TextView txtName = (TextView) view.findViewById(R.id.txtName); 
       if (i == position) { 
        txtName.setTextColor(Color.GREEN); 
        txtName.setBackgroundColor(Color.YELLOW); 
       } else { 
        txtName.setTextColor(Color.YELLOW); 
        txtName.setBackgroundColor(Color.GREEN); 
       } 
      } 
     } 
    }); 
    fillList(); 
} 

private void fillList() { 
    for (int i = 0; i < 30; i++) { 
     DataModel dataModel = new DataModel(); 
     dataModel.setName("Name : " + i); 
     dataModels.add(dataModel); 
    } 
    adapter.notifyDataSetChanged(); 
    } 
} 

NameListAdapter.java
public class NameListAdapter extends BaseAdapter { 
Context context; 
ArrayList<DataModel> dataModels; 
LayoutInflater inflater; 

public NameListAdapter(Context context, ArrayList<DataModel> dataModels) { 
    this.context = context; 
    this.dataModels = dataModels; 
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

@Override 
public int getCount() { 
    return dataModels.size(); 
} 

@Override 
public Object getItem(int position) { 
    return dataModels.get(position); 
} 

@Override 
public long getItemId(int position) { 
    return dataModels.indexOf(getItem(position)); 
} 

private class Holder { 
    TextView txtName; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    Holder holder; 
    if (convertView == null) { 
     holder = new Holder(); 
     convertView = inflater.inflate(R.layout.test_adapter_raw, parent, false); 
     holder.txtName = (TextView) convertView.findViewById(R.id.txtName); 
     convertView.setTag(holder); 
    } else { 
     holder = (Holder) convertView.getTag(); 
    } 
    holder.txtName.setText(dataModels.get(position).getName()); 
    return convertView; 
    } 
} 

test_adapter_raw.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="100dp" 
android:background="#ffffff" 
android:orientation="vertical"> 

<TextView 
    android:id="@+id/txtName" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_margin="5dp" 
    android:background="#949494" 
    android:gravity="center" 
    android:text="Text" 
    android:textAppearance="?android:attr/textAppearanceMedium" 
    android:textColor="#fff" 
    android:textStyle="bold" /> 
</LinearLayout> 

DataModel.java

public class DataModel { 
String name; 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 
} 
+0

嗨Techsky使用標識爲您listItems中的根佈局。由於視圖被重用,你不能直接在onClickListener中修改它的顏色......你必須更新你的適配器,然後,你的適配器將控制視圖的顏色... – W0rmH0le

回答

0

發生這種情況是因爲ListView會回收您的視圖。因此,您同樣的觀點正在用於其他職位。爲了避免混淆,請在適配器內設置clicklistener並處理Holder內部的顏色。

public class NameListAdapter extends BaseAdapter { 
Context context; 
ArrayList<DataModel> dataModels; 
LayoutInflater inflater; 

public NameListAdapter(Context context, ArrayList<DataModel> dataModels) { 
this.context = context; 
this.dataModels = dataModels; 
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

@Override 
public int getCount() { 
    return dataModels.size(); 
} 

@Override 
public Object getItem(int position) { 
    return dataModels.get(position); 
} 

@Override 
public long getItemId(int position) { 
    return dataModels.indexOf(getItem(position)); 
} 

private class Holder { 
    TextView txtName; 
    LinearLayout root_layout; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    Holder holder; 
    if (convertView == null) { 
     holder = new Holder(); 
     convertView = inflater.inflate(R.layout.test_adapter_raw, parent, false); 
     holder.txtName = (TextView) convertView.findViewById(R.id.txtName); 
     holder.root_layout=(LinearLayout)convertView.findViewById(R.id.root_layout) 
     convertView.setTag(holder); 
    } else { 
     holder = (Holder) convertView.getTag(); 
    } 
    holder.txtName.setText(dataModels.get(position).getName()); 

    holder.root_layout.setOnClickListener(new View.OnClickListener(){ 

       holder.txtName.setTextColor(Color.GREEN); 
       holder.txtName.setBackgroundColor(Color.YELLOW); 

       //implement your own logic to remove color on second click 
    }); 


    return convertView; 
    } 
} 

如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/root_layout" 
android:layout_width="match_parent" 
android:layout_height="100dp" 
android:background="#ffffff" 
android:orientation="vertical"> 

<TextView 
android:id="@+id/txtName" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:layout_margin="5dp" 
android:background="#949494" 
android:gravity="center" 
android:text="Text" 
android:textAppearance="?android:attr/textAppearanceMedium" 
android:textColor="#fff" 
android:textStyle="bold" /> 
</LinearLayout> 
+0

如果您使用此方法刪除OnItemClickListener - >將點擊與視圖持有者成員關聯可以防止混淆 – Kushan

+0

感謝您的回答和寶貴努力,但是我需要根據其值對其他列表視圖進行綁定。這就是MainActivity,這就是爲什麼我在活動中使用更新視圖,然後根據這個值我需要過濾另一個listview的值。 –

+0

嗯..對不起,幫不了你。無論如何,你現在知道爲什麼會發生混亂。周圍的方式是使用ViewHolder來設置顏色等...爲什麼不嘗試一個RecyclerView,它強制使一個使用ViewHolder和更有效的一個列表視圖。 – Kushan

0

期間onClick()你不能直接改變了看法,因爲該視圖重新使用....

所以,你改變視圖的顏色,這種觀點會可能在另一個位置重新使用,然後,另一個位置將顯示彩色視圖。

您必須控制適配器中的視圖顏色。這樣,您的活動只更新適配器並調用notifyDataSetChanged()以使ListView更新內容。

您活動代碼

twvTest.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
    @Override 
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
     // Inform the adapter that following item should be displayed in Yellow 
     adapter.displayViewInYellow(position); 
     adapter.notifyDataSetChanged();   
    } 
}); 

你的適配器代碼

public class NameListAdapter extends BaseAdapter { 

    boolean [] arrayOfViewsThatMustShowYellow; 

    public NameListAdapter(Context context, ArrayList<DataModel> dataModels) { 
     ... 
     arrayOfViewsThatMustShowYellow = new boolean[getCount()]; 
    } 

    public void displayViewInYellow(int position) { 
     // boolean array to track view that must be displayed in Yellow 
     arrayOfViewsThatMustShowYellow[position] = true; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     ..... 

     // Following code could be simplified to convertView.setEnabled(arrayOfViewsThatMustShowYellow[position]) 
     if(arrayOfViewsThatMustShowYellow[position] == true) { 
      holder.txtName.setTextColor(Color.GREEN); 
      holder.txtName.setBackgroundColor(Color.YELLOW); 
     } else { 
      holder.txtName.setTextColor(Color.YELLOW); 
      holder.txtName.setBackgroundColor(Color.GREEN); 
     } 
    } 
} 

注意

這是一個例子......這只是共享有關的想法如何去做... 請記住,如果需要更新任何視圖,則需要在適配器內跟蹤此更改(並且絕對不在外面 - 就像ClickListeners或Activity一樣)。

+0

嗨,謝謝你的努力。我想知道適配器中的問題是什麼。正如你所說,我們必須在適配器中完成所有的ListView監聽器,但在我的應用程序中還有另一個活動,我在其中使用了gridview及其在適配器中使用的所有偵聽器,但是也出現了相同的問題。你可以看到鏈接[Gridview適配器問題](http://stackoverflow.com/questions/38247794/listview-update-another-raw-on-update-of-selected-raw) –

0

如果這些名稱的值爲空,則該視圖將爲它設置ramdom值。set「」爲空名稱可能適合它。

+0

但我沒有任何空的名字 –

+0

滾動出現問題 –