0

I have a custom listview which is used to fill up a list, so every item has it's own edittext. When I click in on of them and type in some value, and after that I hide the soft keyboard (little down pointing arrow on the left down corner of the keyboard) the edittext loses the typed in text.

Why and how can I prevent it?

Thanks!

The code of the adapter:

public class CompetitorResultWeightListAdapter extends ArrayAdapter<Competitor> {

    Helper helper = new Helper(getContext());

    private DatabaseReference databaseResult;

    private Activity context;
    private List<Competitor> competitorList;
    private WodResult wodResult;

    public CompetitorResultWeightListAdapter(Activity context, List<Competitor> competitorList) {
        super(context, R.layout.competitor_result_weight_list_layout, competitorList);
        this.context = context;
        this.competitorList = competitorList;
    }

    @NonNull
    @Override
    public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        helper.logD("in CompetitorResultWeightListAdapter - getView");
        databaseResult = FirebaseDatabase.getInstance().getReference("Competitions").child(helper.getsCompetitionID())
                .child("Wods").child(helper.getsWodID()).child("Results");

        LayoutInflater layoutInflater = context.getLayoutInflater();

        convertView = layoutInflater.inflate(R.layout.competitor_result_weight_list_layout, null, true);

        final ViewHolder viewHolder = new ViewHolder();

        TextView tvCompetitorListName = (TextView) convertView.findViewById(R.id.tvCompetitorListName);
        TextView tvCompetitorListNumber = (TextView) convertView.findViewById(R.id.tvCompetitorListNumber);
        viewHolder.etWeight = (EditText) convertView.findViewById(R.id.etCompetitorResultWeight);
        viewHolder.btnSaveResult = (ImageButton) convertView.findViewById(R.id.btnCompetitorResultRepeat);
        convertView.setTag(viewHolder);

        Competitor competitor = competitorList.get(position);

        tvCompetitorListName.setText(competitor.getCompetitorName());
        tvCompetitorListNumber.setText("Rajtszám: " + competitor.getCompetitorNumber());

        //viewHolder.etWeight.setHint("működik");
        //etCompetitorResultWeight.setInputType(InputType.TYPE_NULL);
        //etCompetitorResultWeight.setTextIsSelectable(true);

        viewHolder.btnSaveResult.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewHolder.etWeight.setHint(viewHolder.etWeight.getText() + " kg");
                helper.logD("Edittext text at position " + position + ": " + viewHolder.etWeight.getText().toString().trim());
                helper.setsCompetitorID(getItem(position).getCompetitorID());
                addWodResult(getItem(position).getCompetitorID(),
                        getItem(position).getCompetitorName(),
                        viewHolder.etWeight.getText().toString().trim());
            }
        });

        return convertView;
    }

    private void addWodResult(String id, String name, String result) {
        helper.logD("in addWodResult");
        helper.logD("id: " + id + ", name: " + name + ", result: " + result);

        wodResult = new WodResult(id, name, result);

        databaseResult.child(helper.getsCompetitorID()).setValue(wodResult).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    helper.makeToast(getContext().getResources().getString(R.string.wod_result_data_saved), helper.toastShort);
                    //viewHolder.btnRepeatResult.setBackgroundColor(Color.GREEN);
                } else {
                    helper.makeToast(getContext().getResources().getString(R.string.firebase_data_stored_error), helper.toastShort);
                }
            }
        });
    }

    public class ViewHolder {
        EditText etWeight;
        ImageButton btnSaveResult;
    }
}
lpasztor
  • 157
  • 13

3 Answers3

0

It sounds like your activity/fragment may be being rebuilt every time the keyboard goes away. Put some log statements in your onStart() to see if this is the case.

At very least you can try adding some configChanges to your Activity in the Manifest:

<activity android:name=".MyActivity"
      android:configChanges="orientation|keyboardHidden"
      android:label="@string/app_name">

It's also possible that you're completely recreating the ListView/Adapter, which will also reset all the values. Put log statements in where the ListView is populated to see if this is called multiple times. Normally this state should be saved.

You should also consider saving the user's data in a temporary way (preferences, Singleton level object) as soon as they finish typing--you can use this, but there are other ways too: https://developer.android.com/reference/android/text/TextWatcher.html

wblaschko
  • 3,252
  • 1
  • 18
  • 24
  • I checked (following your advice) and the adapter's getview is called SEVERAL times on keyboard hide, even when I click inside an edittext... That's no good. – lpasztor Sep 27 '17 at 15:07
  • getView will be called as the items normally behind the keyboard are being populated. I'm more concerned about the whole adapter being remade. – wblaschko Sep 28 '17 at 16:06
  • That's what I did, I rewrote the whole adapter from zero, but the result is the same. – lpasztor Sep 28 '17 at 19:40
  • And the problem is that it calls the getview for the items too what are not covered by the keyboard. – lpasztor Sep 28 '17 at 19:54
  • Consider something like this: https://stackoverflow.com/questions/6057702/values-disappearing-from-a-listview-on-scroll-android and save to the array when the values change. – wblaschko Sep 29 '17 at 03:47
  • Actually I "solved" it by using a simple (not custom) listview, and when I click on an item a dialog window pops up, so in this way I can skip the problematic part. – lpasztor Sep 30 '17 at 05:35
0

I also had the same issue... I don't know how efficient it is but what worked for me was:

  1. Create a public static ArrayList variable
  2. Length of this list will be the same as the length of list passed to the adapter
  3. Each Map in the ArrayList will contain all data you are trying to take as input in the ListView
  4. In the adapter, add listeners to the inputs you are taking (Eg. OnTextChangedListener for EditText) and save the inputs into the map of the same position in ArrayList as the input view.
  5. Now, just after the initialization of views in the ListView's Adapter, read values from
    Map of respective position and set the views with the data present in the Map.
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Anurag Bhalekar
  • 830
  • 7
  • 9
0
  1. Add a onTextChangeListener to your EditText https://stackoverflow.com/questions/12191394/change-edittext-text-from-ontextchangelistener
  2. in afterTextChanged update your input in your local competitorList

What is going on here is that you input data, but the data is going nowhere, when the keyboard hides the list gets redrawn, and the list view will draw the content of your competitorList.

I recommend you to use a RecyclerView instead of the ListView. Take a look at this

Pedro Varela
  • 2,296
  • 1
  • 26
  • 32