Search code examples
androidlistviewarraylistandroid-spinner

TextWatcher incorrect selection from database


enter image description hereMy textwatcher is gives me incorrect output in Android Studio. Can anyone suggest me the workaround to solve this issue.

Requirment. "If the course title starts with the user input in edittext then its shows in spinner(Data from database)"

Note: I am using single spinner for multiple purpose 1. Selecting spinner contects 2. showing the spinner value based on edittext user input

My codings.

package com.bar.example.myapplication;


import android.database.Cursor;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;


import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class CourseSearchActivity extends AppCompatActivity {

  private DBHelper db;
  private List < Course > allCoursesList;
  private List < Offering > allOfferingsList;
  private List < Offering > filteredOfferingsList;

  private EditText courseTitleEditText;
  private Spinner ok;
  private ListView offeringsListView;

  // private selectedInstructorName selectedInstructorName;
  private InstructorSpinnerAdapter instructorSpinnerAdapter;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_course_search);

    deleteDatabase(DBHelper.DATABASE_NAME);
    db = new DBHelper(this);
    db.importCoursesFromCSV("courses.csv");

    db.importOfferingsFromCSV("offerings.csv");

    allOfferingsList = db.getAllOfferings();
    filteredOfferingsList = new ArrayList < > (allOfferingsList);

    allCoursesList = db.getAllCourses();

    courseTitleEditText = (EditText) findViewById(R.id.courseTitleEditText);
    courseTitleEditText.addTextChangedListener(courseTitleTextWatcher);

    ok = (Spinner) findViewById(R.id.spinner1);



    // offeringListAdapter = new OfferingListAdapter(this, R.layout.offering_list_item, filteredOfferingsList);
    // ok.setAdapter(offeringListAdapter);
    instructorSpinnerAdapter = new InstructorSpinnerAdapter(this, R.layout.offering_list_item, filteredOfferingsList);

    ArrayAdapter < String > instructorSpinnerAdapter = new ArrayAdapter < String >
      (this, android.R.layout.simple_spinner_item, getAllCourse());
    ok.setAdapter(instructorSpinnerAdapter);

    ok.setOnItemSelectedListener(instructorSpinnerListener);


  }
  private String[] getAllCourse() {
    String[] instructorNames = new String[allCoursesList.size() + 1];
    instructorNames[0] = "[Select Course]";
    for (int i = 1; i < instructorNames.length; i++) {
      instructorNames[i] = allCoursesList.get(i - 1).getTitle();
    }
    return instructorNames;
  }

  public TextWatcher courseTitleTextWatcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
      String input = charSequence.toString().toLowerCase();
      if (input.equals("")) {

      } else {
        String name = ok.getSelectedItem().toString();
        //Toast.makeText(CourseSearchActivity.this, name, Toast.LENGTH_SHORT).show();
        instructorSpinnerAdapter.clear();
        Offering offering;
        for (int j = 0; j < allOfferingsList.size(); j++) {
          // If the course title starts with the user input,
          // add it to the listAdapter
          offering = allOfferingsList.get(j);
          Course course = offering.getCourse();
          if (course.getTitle().toLowerCase().contains(input)) {
            instructorSpinnerAdapter.add(offering);
            instructorSpinnerAdapter.notifyDataSetChanged();
            ok.setSelection(instructorSpinnerAdapter.getCount() - 1);
          }
        }
      }
    }

    @Override
    public void afterTextChanged(Editable editable) {


    }
  };



  public AdapterView.OnItemSelectedListener instructorSpinnerListener = new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView << ? > adapterView, View view, int i, long l) {
      String selectedInstructorName = adapterView.getItemAtPosition(i).toString();
      if (selectedInstructorName.equals("[Select Instructor]")) {
        instructorSpinnerAdapter.clear();
        for (Offering offering: allOfferingsList)
          instructorSpinnerAdapter.add(offering);


      } else {

        instructorSpinnerAdapter.clear();

      }

    }


    @Override
    public void onNothingSelected(AdapterView << ? > adapterView) {
      adapterView.setSelection(0);
      // Toast.makeText(getApplicationContext(), "Why?", Toast.LENGTH_SHORT).show();
    }
  };

  public void reset(View view) {
    courseTitleEditText.setText("");
    ok.setSelection(0);
  }


}

as per suggestion

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
  String input = charSequence.toString().toLowerCase();
  if (input.equals("")) {

  } else {
    String name = ok.getSelectedItem().toString();
    //Toast.makeText(CourseSearchActivity.this, name, Toast.LENGTH_SHORT).show();
    instructorSpinnerAdapter.clear();
    Offering offering;
    for (int j = 0; j < allOfferingsList.size(); j++) {
      // If the course title starts with the user input,
      // add it to the listAdapter
      offering = allOfferingsList.get(j);
      Course course = offering.getCourse();
      if (course.getTitle().toLowerCase().contains(input)) {
        if (course.getTitle().toLowerCase().startsWith(input))
          instructorSpinnerAdapter.add(offering);
        instructorSpinnerAdapter.notifyDataSetChanged();
        ok.setSelection(instructorSpinnerAdapter.getCount() - 1);
      }
    }
  }
}

error

04-26 10:35:46.394 31756-31756/com.bar.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.bar.example.myapplication, PID: 31756
    java.lang.UnsupportedOperationException
        at java.util.AbstractList.remove(AbstractList.java:161)
        at java.util.AbstractList$Itr.remove(AbstractList.java:374)
        at java.util.AbstractList.removeRange(AbstractList.java:571)
        at java.util.AbstractList.clear(AbstractList.java:234)
        at android.widget.ArrayAdapter.clear(ArrayAdapter.java:285)
        at com.bar.example.myapplication.CourseSearchActivity$1.onTextChanged(CourseSearchActivity.java:95)
        at android.widget.TextView.sendOnTextChanged(TextView.java:8187)
        at android.widget.TextView.handleTextChanged(TextView.java:8249)
        at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:10371)
        at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:1208)
        at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:578)
        at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:509)
        at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:508)
        at android.view.inputmethod.BaseInputConnection.replaceText(BaseInputConnection.java:844)
        at android.view.inputmethod.BaseInputConnection.setComposingText(BaseInputConnection.java:617)
        at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:408)
        at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:93)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Current view is ..

enter image description here

instead of this i need to enter database x and spinner should y screen follows

enter image description here

my database follows.

enter image description here

I am trying to get single input and multiple output. screen example

enter image description here

revised code

public TextWatcher courseTitleTextWatcher = new TextWatcher() {
  @Override
  public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

  }
  @Override
  public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    String input = charSequence.toString().toLowerCase();
    ArrayAdapter adapter = (ArrayAdapter) ok.getAdapter();
    ArrayAdapter adapter1 = (ArrayAdapter) ok1.getAdapter();
    adapter.clear();
    adapter1.clear();
    if (input.equals("")) {
      adapter.addAll(getAllCourse());
      adapter1.addAll(getAllCourse());
    } else {
      Course course;

      for (int j = 0; j < allCoursesList.size(); j++) {
        // If the course title starts with the user input,
        // add it to the listAdapter
        course = allCoursesList.get(j);
        if (course.getAlpha().toLowerCase().startsWith(input) || course.getNumber().toLowerCase().startsWith(input)) {
          adapter.add(course.getTitle());
          adapter1.add(course.getNumber());
        }
      }
    }
    adapter.notifyDataSetChanged();
    if (adapter.getCount() != 0) ok.setSelection(0);
    if (adapter1.getCount() != 0) ok1.setSelection(0);
  }
  @Override
  public void afterTextChanged(Editable editable) {


  }
};

public AdapterView.OnItemSelectedListener instructorSpinnerListener = new AdapterView.OnItemSelectedListener() {
  @Override
  public void onItemSelected(AdapterView << ? > adapterView, View view, int i, long l) {
    String selectedInstructorName = adapterView.getItemAtPosition(i).toString();
    if (selectedInstructorName.equals("[Select Instructor]")) {
      instructorSpinnerAdapter.clear();
      for (Offering offering: allOfferingsList)
        instructorSpinnerAdapter.add(offering);


    } else {

      instructorSpinnerAdapter.clear();

    }

  }


  @Override
  public void onNothingSelected(AdapterView << ? > adapterView) {
    adapterView.setSelection(0);

    // Toast.makeText(getApplicationContext(), "Why?", Toast.LENGTH_SHORT).show();
  }
};

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

  deleteDatabase(DBHelper.DATABASE_NAME);
  db = new DBHelper(this);
  db.importCoursesFromCSV("courses.csv");

  db.importOfferingsFromCSV("offerings.csv");
  Button reset = (Button) findViewById(R.id.resetButton);
  allOfferingsList = db.getAllOfferings();
  filteredOfferingsList = new ArrayList < > (allOfferingsList);

  allCoursesList = db.getAllCourses();

  courseTitleEditText = (EditText) findViewById(R.id.courseTitleEditText);
  courseTitleEditText.addTextChangedListener(courseTitleTextWatcher);

  ok = (Spinner) findViewById(R.id.spinner1);
  ok1 = (Spinner) findViewById(R.id.spinner2);

  // offeringListAdapter = new OfferingListAdapter(this, R.layout.offering_list_item, filteredOfferingsList);
  // ok.setAdapter(offeringListAdapter);
  instructorSpinnerAdapter = new InstructorSpinnerAdapter(this, R.layout.offering_list_item, filteredOfferingsList);

  ArrayAdapter < String > instructorSpinnerAdapter = new ArrayAdapter < String >
    (this, android.R.layout.simple_spinner_item, getAllCourse());
  ok.setAdapter(instructorSpinnerAdapter);
  ok1.setAdapter(instructorSpinnerAdapter);
  ok.setOnItemSelectedListener(instructorSpinnerListener);

  ok1.setOnItemSelectedListener(instructorSpinnerListener);
}

it works but some time not . could you check and advise...

error...attachedenter image description here

Another Condition:

Select spinner2 selection based on spinner screenshot attached. how to swap the same . pls advise. enter image description here


Solution

  • Try the code below:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_course_search);
    
        deleteDatabase(DBHelper.DATABASE_NAME);
        db = new DBHelper(this);
        db.importCoursesFromCSV("courses.csv");
    
        db.importOfferingsFromCSV("offerings.csv");
        Button reset = (Button) findViewById(R.id.resetButton);
        allOfferingsList = db.getAllOfferings();
        filteredOfferingsList = new ArrayList <> (allOfferingsList);
    
        allCoursesList = db.getAllCourses();
    
        courseTitleEditText = (EditText) findViewById(R.id.courseTitleEditText);
        courseTitleEditText.addTextChangedListener(courseTitleTextWatcher);
    
        ok = (Spinner) findViewById(R.id.spinner1);
        ok1 = (Spinner) findViewById(R.id.spinner2);
    
        // offeringListAdapter = new OfferingListAdapter(this, R.layout.offering_list_item, filteredOfferingsList);
        // ok.setAdapter(offeringListAdapter);
        instructorSpinnerAdapter = new InstructorSpinnerAdapter(this, R.layout.offering_list_item, filteredOfferingsList);
    
        // The two spinners need to have different adapters as they will use different datasets.
        ok.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, getAllCourse()));
        ok1.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, getAllCourseNumber()));
        // The two spinner can have same listener.
        ok.setOnItemSelectedListener(instructorSpinnerListener);
        ok1.setOnItemSelectedListener(instructorSpinnerListener);
    }
    
    private ArrayList<String> getAllCourse() {
        ArrayList<String> instructorNames = new ArrayList<>();
        instructorNames.add("[Select Course]");
        for (int i = 0; i < allCoursesList.size(); i++) {
            instructorNames.add(allCoursesList.get(i).getTitle());
        }
        return instructorNames;
    }
    
    private ArrayList<String> getAllCourseNumber() {
        ArrayList<String> instructorNames = new ArrayList<>();
        instructorNames.add("[Select Course]");
        for (int i = 0; i < allCoursesList.size(); i++) {
            instructorNames.add(allCoursesList.get(i).getNumber());
        }
        return instructorNames;
    }
    
    public TextWatcher courseTitleTextWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            String input = charSequence.toString().toLowerCase();
            // Toast.makeText(getApplicationContext(), input, Toast.LENGTH_LONG).show();
            ArrayAdapter adapter = (ArrayAdapter) ok.getAdapter();
            ArrayAdapter adapter1 = (ArrayAdapter) ok1.getAdapter();
            adapter.clear();
            adapter1.clear();
            if (input.equals("")) {
                adapter.addAll(getAllCourse());
                adapter1.addAll(getAllCourseNumber());
            } else {
                Course course;
                for (int j=0; j < allCoursesList.size(); j++) {
                    // If the course alpha/number starts with the user input,
                    // add it to the listAdapter
                    course = allCoursesList.get(j);
                    if (course.getAlpha().toLowerCase().startsWith(input) || course.getNumber().toLowerCase().startsWith(input)) {
                        adapter.add(course.getTitle());
                        adapter1.add(course.getNumber());
                    }
                }
            }
            adapter.notifyDataSetChanged();
            adapter1.notifyDataSetChanged();
            if (adapter.getCount() != 0) ok.setSelection(0);
            if (adapter1.getCount() != 0) ok1.setSelection(0);
        }
        @Override
        public void afterTextChanged(Editable editable) {}
    };
    
    public AdapterView.OnItemSelectedListener instructorSpinnerListener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            //String selectedInstructorName = adapterView.getItemAtPosition(i).toString();
    
            // No matter which spinner is selected, get item from the ok [Title] spinner.
            String selectedInstructorName = ok.getItemAtPosition(i).toString();
            if (selectedInstructorName.equals("[Select Instructor]")) {
                instructorSpinnerAdapter.clear();
                for (Offering offering: allOfferingsList)
                    instructorSpinnerAdapter.add(offering);
            } else {
                instructorSpinnerAdapter.clear();
            }
        }
        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {
            adapterView.setSelection(0);
            // Toast.makeText(getApplicationContext(), "Why?", Toast.LENGTH_SHORT).show();
        }
    };
    

    I am not sure why use getAlpha() in TextWatcher as you show that alpha is always CS. If the code does not work, then in getAllCourseNumber() change allCoursesList.get(i).getNumber() to allCoursesList.get(i).getAlpha(), so we can have a list of alpha for checking.

    Hope that helps!

    Updated the OnItemSelectedListener:

        public AdapterView.OnItemSelectedListener instructorSpinnerListener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            // Sync the selection of the two spinners.
            if(adapterView.getId() == R.id.spinner1){
                ok1.setOnItemSelectedListener(null);
                ok1.setSelection(i);
                ok1.setOnItemSelectedListener(this);
            }else{
                ok.setOnItemSelectedListener(null);
                ok.setSelection(i);
                ok.setOnItemSelectedListener(this);
            }
            // No matter which spinner is selected, get item from the ok [Title] spinner.
            String selectedInstructorName = ok.getItemAtPosition(i).toString();
            if (selectedInstructorName.equals("[Select Instructor]")) {
                instructorSpinnerAdapter.clear();
                for (Offering offering: allOfferingsList)
                    instructorSpinnerAdapter.add(offering);
            } else {
                instructorSpinnerAdapter.clear();
            }
        }
        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {
            adapterView.setSelection(0);
            // Toast.makeText(getApplicationContext(), "Why?", Toast.LENGTH_SHORT).show();
        }
    };