简体   繁体   中英

ListView updated from EditText

I have a Custom Listview that it is updated from a EditText component in a dialog. I have the custom row, the adapter class and the custom dialog all working but I can't seem to trigger the code in the adatper class that would add the text from the edit text control to the list. Here is my activity code, let me know if you want the adapter code. It worked before I added the custom row and adapter to the list :(

Symptom of problem: emailAdapter.notifyDataSetChanged(); does nothing

public class InvitePlayers_Activity extends Activity {
    ListViewAdapter emailAdapter = null;
    ImageView imgView_mail;
    ImageView imgView_confirm;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE); //remove title bar
        setContentView(R.layout.activity_inviteplayers);

        //Generate list View from ArrayList
        displayListView();
    }

    private void displayListView() {
        //assign controls
        final ListView listView = (ListView) findViewById(R.id.listView_invitePlayers);
        imgView_mail = (ImageView)findViewById(R.id.imgView_mail);

        //Test data
        ArrayList<String> inviteNew = new ArrayList<String>();
        final ArrayList<ArrayList<String>> inviteList = new ArrayList<ArrayList<String>>();

        emailAdapter = new ListViewAdapter(this,inviteList);
        listView.setAdapter(emailAdapter);

        // Assign adapter to ListView
        listView.setTextFilterEnabled(true);

        //Edit listeners
        imgView_mail.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view)
            {
                        //variables
                        final String enteredMail = "testListViewEntry";
                        final ArrayList<ArrayList<String>> inviteList = new ArrayList<ArrayList<String>>();
                        ArrayList<String> invite = new ArrayList<String>();
                        invite.add(0, enteredMail);//add first email
                        invite.add(1,"icon_invitestatussent.png"); //add first status icon
                        inviteList.add(invite);
                        emailAdapter.notifyDataSetChanged();
                        listView.setAdapter(emailAdapter);
            }
        });
    }
}

Adapter code as requested

public class ListViewAdapter extends BaseAdapter {
    private Activity context;
    ArrayList<ArrayList<String>> inviteDetails = new ArrayList<ArrayList<String>>();
    public ListViewAdapter(Activity context, ArrayList<ArrayList<String>> inviteDetails ) {
        this.inviteDetails = inviteDetails;
        this.context = context;
    }

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

    @Override
    public Object getItem(int i) {
        return inviteDetails.get(i).get(0);
    }

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

    public View getView(int position, View view, ViewGroup parent){
        //Inflater
        LayoutInflater inflater = context.getLayoutInflater();

        //get row view
        if (view == null) {
            LayoutInflater mInflater = (LayoutInflater)
                    context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

            view = mInflater.inflate(R.layout.list_item_email, null);
        }

        //assign controls
        final TextView textView_playerEmail = (TextView) view.findViewById(R.id.textView_playerEmail);
        ImageView imgView_inviteStatus = (ImageView) view.findViewById(R.id.imgView_inviteStatus);

        //Assign control values that are dynamic
        textView_playerEmail.setText(inviteDetails.get(position).get(0));
        imgView_inviteStatus.setImageResource(R.drawable.icon_invitestatussent);

        return view;
    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
    }
}

Custom row xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="10dp"
        android:textSize="16sp"
        android:id="@+id/textView_playerEmail"
        android:textColor="@color/white"
        android:text="item1">
    </TextView>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imgView_inviteStatus" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imgView_remove"
        android:src="@drawable/btn_cancel" />
</LinearLayout>

The activity layout

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="20"
            android:background="@color/yellow"
            android:layout_margin="20dp"
            android:padding="5dp">

            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:weightSum="1"
                android:gravity="left|center">


                <ImageView
                    android:layout_width="45dp"
                    android:layout_height="34dp"
                    android:id="@+id/imgView_mail"
                    android:src="@drawable/btn_mail"
                    android:layout_weight="0.22"
                    android:padding="3dp" />
            </LinearLayout>

            <ListView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/listView_invitePlayers"
                android:layout_gravity="center_horizontal" />
        </LinearLayout>

        <ImageView
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:id="@+id/btn_confirm"
            android:src="@drawable/btn_confirm"
            android:clickable="false"
            android:adjustViewBounds="true"
            android:layout_gravity="center_horizontal"
            android:padding="2dp"
            android:layout_weight="1" />
    </LinearLayout>

</FrameLayout>

在此处输入图片说明

Well, for what we discussed, you wanted something like this:

最后结果

When you want to make a custom ListView , you have to write your own adapter. In this particular case I'm subclassing the BaseAdapter class.

This custom adapter will take hold of my data model, and will inflate the data to my ListView rows.

First, I'll create the XML of my custom row. You can see the code below.

item_mail.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test text"
        android:id="@+id/tv_mail"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/iv_icon"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:src="@android:drawable/ic_menu_report_image" />
</RelativeLayout>

Here I've created a row that displays a text and an image.

Now, I'll create my custom adapter to handle this XML. As you can see below.

MailAdapter.java

public class MailAdapter extends BaseAdapter {

    private static final String LOG_TAG = MailAdapter.class.getSimpleName();

    private Context context_;
    private ArrayList<ArrayList<String>> mailitems;

    public MailAdapter(Context context, ArrayList<ArrayList<String>> mailitems) {
        this.context_ = context;
        this.mailitems = mailitems;
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater mInflater = (LayoutInflater)
                    context_.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

            convertView = mInflater.inflate(R.layout.item_mail, null);
        }

        TextView tv_mail = (TextView) convertView.findViewById(R.id.tv_mail);
        ImageView iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);

        String mail = mailitems.get(position).get(0);
        String icon = mailitems.get(position).get(1);

        Log.d(LOG_TAG,"Mail: " + mail + " mail_icon: " + icon);

        tv_mail.setText(mail);
        // iv_icon.setImageURI(); Here you can do whatever logic you want to update your image, using URI's, ID's, or something else.

        return convertView;
    }
}

Ok. Now we have everything to make this work. In your Activity class, do something like that:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView
        android:text="@string/hello_world"
        android:id="@+id/tv_header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/tv_header">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Add mail"
            android:id="@+id/button"
            android:layout_gravity="center" />

        <ListView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/listView" />
    </LinearLayout>

</RelativeLayout>

MainActivity.java

public class MainActivity extends ActionBarActivity {

    private int numMail = 1; // Dummy int to create my items with different numbers.

    private MailAdapter mailAdapter; // Your custom adapter.

    private ArrayList<ArrayList<String>> mailItems; // This is going to be your data structure, everytime you change it, call the notifyDataSetChanged() method.

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

        Button bt = (Button) findViewById(R.id.button);
        ListView lv_mail = (ListView) findViewById(R.id.listView);
        mailItems = new ArrayList<>();
        mailAdapter = new MailAdapter(this,mailItems);
        lv_mail.setAdapter(mailAdapter);

        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addItem(); // The method I'm using to insert the item. Look for it below.
            }
        });
    }

    // Here I'm creating a new ArrayList, and appending it to my 'mailItems' Array. After that, I'm notifying the adapter that my data changed.
    private void addItem() {
        ArrayList<String> mail = new ArrayList<>();

        mail.add(0,"mail " + numMail++);
        mail.add(1,"path_to_image"); // Depending on what you want to do, put your path, URI, or whatever other way you want to store that image data.

        mailItems.add(mail); // Inserting the data on the ArrayList.
        mailAdapter.notifyDataSetChanged(); // Notifying the adapter that my ArrayList was modified.
    }
}

This should do the trick.

I guess your problem was that you weren't updating the same ArrayList that was in your custom adapter. That's why when you called notifyDataSetChanged() nothing happened, I mean. You were creating a new ArrayList , which wasn't the same that was in your adapter. So here's what I did... I've made the ArrayList global, and then I've used it in my custom adapter constructor. After that, when the user triggers the onClick() method of my button, I'm inserting some new data on my global Array, and then I'm notifying the adapter that the data changed.

You can read a little more about that here and I've found a similar question here , which you can read as well.

Edit: Another related question , which might be an interesting read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM