Vinh Nguyễn
Vinh Nguyễn

Reputation: 21

Trouble with custom listview

I'm using a listview to display an item with a textview and a button. If I click the button, an item will be removed. An item is added by input of EditText. Here is my code. My problem is when I run this app, I can't add an new item. Problem

This is my MainActivity

package com.example.myapplication;

import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    public ArrayList<String> arrayList;
    private MyAdapter myAdapter;
    private Button addButton;
    private Activity activity;

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

        arrayList = new ArrayList<>();

        listView = (ListView) findViewById(R.id.list_view);
        addButton = (Button) findViewById(R.id.addBtn);

        addButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EditText input = findViewById(R.id.input);
                String addItem = input.getText().toString();

                if(addItem.length()>0){
                    arrayList.add(addItem);
                    input.setText("");
                }
                else {
                    Toast.makeText(getApplicationContext(),"Please Enter ...", Toast.LENGTH_SHORT).show();
                }
            }
        });

        myAdapter = new MyAdapter(this, arrayList);
        listView.setAdapter(myAdapter);
    }

    public class MyAdapter extends BaseAdapter {
        @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(final int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = activity.getLayoutInflater();
            View view = convertView;
            view = inflater.inflate(R.layout.item, null);
            TextView textView = (TextView) view.findViewById(R.id.tv_name);
            Button rmvButton = (Button) view.findViewById(R.id.rmvButton);
            textView.setText(arrayList.get(position));
            rmvButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    arrayList.remove(position);
                    notifyDataSetChanged();
                }
            });
            return view;
        }

        public MyAdapter(Activity a, ArrayList<String> list) {
            activity = a;
            arrayList = list;
        }
    }
}

This is my main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/input"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/addBtn"
            android:layout_alignParentLeft="true"/>
        <Button
            android:id="@+id/addBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_marginEnd="6dp"
            android:layout_marginRight="6dp"
            android:text="Add" />
    </RelativeLayout>

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

And my item.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"
    android:padding="16dp">

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="329dp"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/rmvButton"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:background="@android:color/holo_orange_light"
        android:text="X" />
</LinearLayout>

Upvotes: 1

Views: 58

Answers (3)

Rajan Surani
Rajan Surani

Reputation: 11

You need to notify the adapter about the data being added to the list and to do that you should call notifyDataSetChanged() method like this.

addButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            EditText input = findViewById(R.id.input);
            String addItem = input.getText().toString();

            if(addItem.length()>0){
                arrayList.add(addItem);
                input.setText("");
                mAdapter.notifyDataSetChanged();
            }
            else {
                Toast.makeText(getApplicationContext(),"Please Enter ...", Toast.LENGTH_SHORT).show();
            }
        }
    });

The alternate method for this can be to add data directly to the adapter.

addButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            EditText input = findViewById(R.id.input);
            String addItem = input.getText().toString();

            if(addItem.length()>0){
                mAdapter.add(additem);
                input.setText("");
            }
            else {
                Toast.makeText(getApplicationContext(),"Please Enter ...", Toast.LENGTH_SHORT).show();
            }
        }
    });

When you use mAdapter.add() it will automatically notify that the dataset has been changed.

Upvotes: 1

DevHyperCoder
DevHyperCoder

Reputation: 943

When you first define your ArrayList using arrayList = new ArrayList<>();, you define a empty array list and then set the adapter.

The next time when you change the contents of the list you should call notifyDataSetChanged(); on the adapter.

so in your onClickListener() you would do

addButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EditText input = findViewById(R.id.input);
                String addItem = input.getText().toString();

                if(addItem.length()>0){
                    arrayList.add(addItem);
                    //call notifyDataSetChanged()
                    mAdapter.notifyDataSetChanged();
                    input.setText("");
                }
                else {
                    Toast.makeText(getApplicationContext(),"Please Enter ...", Toast.LENGTH_SHORT).show();
                }
            }
        });

Upvotes: 1

Uuu Uuu
Uuu Uuu

Reputation: 1282

You have to notify your adapter when you add new item

if(addItem.length()>0){
        arrayList.add(addItem);
        myAdapter.notifyItemInserted(arrayList.size()-1);
        input.setText("");
    }

Upvotes: 1

Related Questions