Listview视图在滚动时随机更新

时间:2016-07-14 13:17:42

标签: android listview adapter

我正在使用一个列表视图绑定一些项目,点击后我想更新列表视图的视图但是当我滚动它时,该效果应用于其他视图,如果滚动更多时间,它会随机改变位置。

这是我的代码。

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

3 个答案:

答案 0 :(得分:0)

您无法在onClick()期间直接更改视图,因为该视图已重新使用....

因此,您更改了视图的颜色,该视图可能会在另一个位置重新使用,然后,另一个位置将显示彩色视图。

您必须控制适配器中的视图颜色。这样,您的Activity仅更新Adapter并调用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中)。

答案 1 :(得分:0)

如果名称为空值,则视图持有者将为it.set&#34;&#34;设置ramdom值。对于空名可能适合它。

答案 2 :(得分: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;
  }
}

为Listitems根布局使用Id,如下所示

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