2

我是 android 新手,我刚刚开始编写一个简单的应用程序来尝试不同的事情。

我正在编写一个 ListView(并且,以同样的方式编写一个 GridView),但我有一些地方出错了。每个项目都是一对图像和一个文本字段。

| 图片 | __文本__ |

在将所选项目传递给下一个活动之前,我希望能够选择任意数量的列表项,让它们在所有选择过程中保持启发。如果我想取消选择其中一个,我只需重新单击该项目即可使选择消失。为此,我使用了一个自定义选择器,以便在按下项目时它会改变颜色。

如果项目都包含在屏幕中,则一切正常。但是一旦它们的数量增加并且回收开始,从屏幕上出来的选定项目的启发就消失了。我已经调试了项目的状态,并且那些启发丢失的仍然被正确选择,所以我认为这只是一个项目在退出设备屏幕后恢复时如何重新加载图形的问题。

这是活动布局的代码:

<!-- items_selection.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="match_parent"
android:orientation="vertical"
android:background="@color/Background">

<ListView
    android:id="@+id/item_list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:divider="@color/divider"
    android:dividerHeight="3dp"
    android:choiceMode="multipleChoice"
    android:listSelector="@drawable/list_selector">
</ListView>

</LinearLayout>

这是行项目布局:

<!-- list_row.xml --> 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip" >

<LinearLayout
    android:id="@+id/item_list_item"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_marginRight="5dip"
    android:padding="3dip" >
    <ImageView
        android:id="@+id/item_image"
        android:layout_width="@dimen/img_side"
        android:layout_height="@dimen/img_side" />
</LinearLayout>

<TextView
    android:id="@+id/item_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/item_list_item"
    android:layout_centerVertical="true"
    android:textColor="@color/black"
    android:textSize="@dimen/textnorm"
    />

</RelativeLayout>

这是我使用的选择器:

<!-- list_selector.xml -->

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item
    android:state_selected="false"
    android:state_pressed="false"
    android:drawable="@drawable/rect" />

<item
    android:state_pressed="true"
    android:drawable="@drawable/rect_sel" />

<item
    android:state_selected="true"
    android:state_pressed="false"
    android:drawable="@drawable/rect_sel" />

</selector>


<!-- rect.xml -->

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<gradient
    android:startColor="#D5DDE0"
    android:centerColor="#e7e7e8"
    android:endColor="#CFCFCF"
    android:angle="270" />

</shape>


<!-- rect_sel.xml -->

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<gradient
    android:startColor="#78DDFF"
    android:centerColor="#16cedb"
    android:endColor="#09adb9"
    android:angle="270" />

</shape>

这是活动的代码:

public class ItemSelection extends AppCompatActivity {

private int numitems;
private ListView listview;
private ArrayList<Item> items = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.items_selection);

    numitems = 15;
    build_list();

    listview = (ListView) findViewById(R.id.item_list);
    listview.setAdapter(new ListAdapter(this, items));

}

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.next_btn, menu);
    return true;
}

    public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    switch(id){
        case R.id.next_btn:
            Intent intent = new Intent (this, nextActivity.class);
            intent.putStringArrayListExtra("items", Chosen_Items());
            startActivity(intent);
            return true;
        default:
            Toast.makeText(getApplicationContext(), "ERROR", Toast.LENGTH_SHORT).show();
            return super.onOptionsItemSelected(item);
    }
}

private void build_list() {
     //Populates the item list with more items than the screen can support.
    }


private ArrayList<String> Chosen_Items(){

    ArrayList<String> selitems = new ArrayList<>();

    for (int i=0; i<numitems; i++){
        if (items.get(i).isSelected()){
            selitems.add(items.get(i).getName());
        }
    }

    return selitems;
}

这是 listAdapter 的代码:

public class ListAdapter extends BaseAdapter {

private ArrayList <Item> items;
private Activity sActivity;

public ListAdapter(Activity sActivity, ArrayList<Item> items) {
    this.sActivity = sActivity;
    this.items = items;
}

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

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

@Override
public long getItemId(int position) {
    return position;
}


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

    View view = convertView;
    ViewHolder holder;

    if(view == null) {
        LayoutInflater li = sActivity.getLayoutInflater();
        view = li.inflate(R.layout.list_row, null);

        holder = new ViewHolder();
        holder.text = (TextView)view.findViewById(R.id.item_name);
        holder.img = (ImageView)view.findViewById(R.id.item_image);

        view.setTag(holder);
    }

    else {
        holder = (ViewHolder)view.getTag();
    }

    holder.text.setText(items.get(position).getName());
    holder.img.setImageResource(items.get(position).getImage());


    view.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View viewitem) {

            if (!viewitem.isSelected() && !items.get(position).isSelected()) {
                viewitem.setSelected(true);
                items.get(position).setSelected(true);
            }

            else {
                viewitem.setSelected(false);
                items.get(position).setSelected(false);
            }
        }

    });

    return view;
}

private static class ViewHolder{
    public TextView text;
    public ImageView img;
}

}

我已经尝试手动设置重新进入屏幕的项目的背景颜色(通过使用

view.setBackgroundResource(R.drawable.rect_sel)

在适配器中,在单击处理程序之前),但问题仍然存在。谁能帮我解决问题?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

选择器似乎没有遵循项目及其视图的回收。在这种情况下,必须有一个更好、更优雅的解决方案利用选择器。但在我所做的所有尝试中,没有一个奏效。此解决方案是最好的解决方法,并且不使用选择器。

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

View view = convertView;
ViewHolder holder;

if(view == null) {
    LayoutInflater li = sActivity.getLayoutInflater();
    view = li.inflate(R.layout.list_row, null);

    holder = new ViewHolder();
    holder.text = (TextView)view.findViewById(R.id.item_name);
    holder.img = (ImageView)view.findViewById(R.id.item_image);

    view.setTag(holder);
}

else {
    holder = (ViewHolder)view.getTag();
}

holder.text.setText(items.get(position).getName());
holder.img.setImageResource(items.get(position).getImage());

if(items.get(position).isSelected()){
    view.setBackgroundResource(R.drawable.rect_sel);
}else{
    view.setBackgroundResource(R.drawable.rect);
}

view.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View viewitem) {

        if (!viewitem.isSelected() && !items.get(position).isSelected()) {
            viewitem.setBackgroundResource(R.drawable.rect_sel);
            viewitem.setSelected(true);
            items.get(position).setSelected(true);
        }

        else {
            viewitem.setBackgroundResource(R.drawable.rect);
            viewitem.setSelected(false);
            items.get(position).setSelected(false);
        }
    }
    });

    return view;
}

private static class ViewHolder{
    public TextView text;
    public ImageView img;
}

list_row.xml文件中,可以只删除以下行:

android:background="@drawable/list_selector"
4

3 回答 3

0

您必须在 getView 方法中定义视图的当前选择状态。

添加这一行:

viewitem.setSelected(items.get(position).isSelected());

在创建了viewholder之后:

holder.img.setImageResource(items.get(position).getImage());
viewitem.setSelected(items.get(position).isSelected());
于 2015-09-29T07:58:36.570 回答
0

在您的getView()方法中,只需添加此测试:

if (items.get(position).isSelected()){
   view.setBackgroundResource(R.drawable.rect_sel);
} else {
   view.setBackgroundResource(R.drawable.rect);
}

或者只是view.setSelected(items.get(position).isSelected());。虽然您已经有一个列表项的选择器。

于 2015-09-29T07:59:30.147 回答
0

我认为您应该为您的 RelativeLayout 设置 ID,然后将其添加到 ViewHolder

private static class ViewHolder{
    public TextView text;
    public ImageView img;
    RelativeLayout rl;
}

之后,您在单击RelativeLayout 时处理事件,然后更改RelativeLayout 的背景

 public View getView(...)
    ...
    ...
    // you should update the state of relative layout first
     if (items.get(position).isSelected()) {
        holder.setBackgroundColor(Color.parseColor("#ffff00"));
    }else{
         holder.setBackgroundColor(Color.parseColor("#ff0000"));
    }

    holder.rl.setOnClickListener(new View.OnClickListener(){ //remmember it is rl.setOnClick... not view.setOnClick...
        public void onClick(View v) {
              if (!items.get(position).isSelected()) {
                  items.get(position).setSelected(true);
                  holder.setBackgroundColor(Color.parseColor("#ffff00"));
              }else {
                  items.get(position).setSelected(false);
                  holder.setBackgroundColor(Color.parseColor("#ff0000"));
              }
        }
    });
}

建议
您应该像这样修改您的行布局(我已经删除了 LinearLayout 但新布局仍然很好)

    <!-- list_row.xml --> 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip" >

  <ImageView 
     android:id="@+id/item_image"
     android:layout_marginRight="5dip"
     android:padding="3dip"
     android:layout_alignParentLeft="true"
     android:layout_width="@dimen/img_side"
     android:layout_height="@dimen/img_side" />

<TextView
    android:id="@+id/item_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/item_image"
    android:layout_centerVertical="true"
    android:textColor="@color/black"
    android:textSize="@dimen/textnorm"
    />

</RelativeLayout>

请记住,您的列表行布局更简单,然后您的列表视图将滚动更快、更流畅并防止一些烦人的错误。

希望这有帮助

于 2015-09-29T07:59:51.780 回答