Search code examples
androidlistviewandroid-listviewandroid-edittextandroid-listfragment

How can I point to EditText elements that are generated dynamically in a ListView in Android?


I am creating a ListView in a ListFragment and it is being populated dynamically, and I have no clue how many items are going to be there. Now I need the user to set the text of EditTexts for each item in the ListView in order to save this text by clicking one single button. My question is, how can I point to the EditText of each item when in fact I have only one EditText in the layout. My code just saves the first EditText text in the list. Does anyone have an idea? I am sorry! I am kind of new to Android.

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        final ViewHolder viewHolder;
        // General ListView optimization code.
        if (view == null) {
            view = mInflater.inflate(R.layout.listitem_device, null);
            viewHolder = new ViewHolder();
            viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
            viewHolder.deviceName = (EditText) view.findViewById(R.id.device_name);
            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }

        BluetoothDevice device = mLeDevices.get(i);
        viewHolder.deviceAddress.setText(device.getAddress());

        saveNode.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                for (int j = 0; j < mLeDeviceListAdapter.getCount() ; j++) {
                    String name = viewHolder.deviceName.getText().toString();
                    String address = viewHolder.deviceAddress.getText().toString();
                    handler = new DataHandler(getActivity().getBaseContext());
                    handler.open();
                    handler.insertNode(address, name);
                    Toast.makeText(getActivity().getBaseContext(), "Node " + name + " inserted", Toast.LENGTH_LONG).show();
                    handler.close();
                }
            }
        });

        return view;
    }

Solution

  • I actually shouldn't have had the button onClick method in the getView() at all. It should be in the onCreate like here:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.scan_activity, container, false);
    
        mHandler = new Handler();
        saveNode = (Button) rootView.findViewById(R.id.save_node_button);
    
        saveNode.setOnClickListener(new View.OnClickListener() {
    
            @Override
            public void onClick(View arg0) {
                for (int j = 0; j < mLeDeviceListAdapter.getCount() ; j++) {
    
                    int wantedPosition = j; // Whatever position you're looking for
                    int firstPosition = mLeDeviceListView.getFirstVisiblePosition() - mLeDeviceListView.getHeaderViewsCount(); // This is the same as child #0
                    int wantedChild = wantedPosition - firstPosition;
                    // Say, first visible position is 8, you want position 10, wantedChild will now be 2
                    // So that means your view is child #2 in the ViewGroup:
                    if (wantedChild < 0 || wantedChild >= mLeDeviceListView.getChildCount()) {
                      //Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
                      return;
                    }
                    // Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
                    View wantedView = mLeDeviceListView.getChildAt(wantedChild);
    
                    nodeName = (EditText) wantedView.findViewById(R.id.device_name);
                    nodeAddress = (TextView) wantedView.findViewById(R.id.device_address);
    
                    name = nodeName.getText().toString();
                    address = nodeAddress.getText().toString();
    
                    handler = new DataHandler(getActivity().getBaseContext());
                    handler.open();
                    handler.insertNode(address, name);
                    Toast.makeText(getActivity().getBaseContext(), "Node " + name + " inserted", Toast.LENGTH_LONG).show();
                    handler.close();
                 }
            }
        });
        return rootView;
    }
    

    And the getView() function should look like this:

    @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            final ViewHolder viewHolder;
            // General ListView optimization code.
            if (view == null) {
                view = mInflater.inflate(R.layout.listitem_device, null);
                viewHolder = new ViewHolder();
                viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
                viewHolder.deviceName = (EditText) view.findViewById(R.id.device_name);
                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }
    
            BluetoothDevice device = mLeDevices.get(i);
            viewHolder.deviceAddress.setText(device.getAddress());
            return view;
        }