Hot questions for Using Android EditText in android recyclerview

Top Java Programmings / Android EditText / android recyclerview

Question:

TL;DR I have a RecyclerView of EditTexts. When the user is focused on EditText #1 and taps on EditText #2, I want EditText #2 to get focus but I don't want the ReyclerView to scroll. How can I achieve this?


I'm trying to work with a RecyclerView populated with a bunch of EditTexts. When I'm focused on one EditText and I click on another, the RecyclerView scrolls so that the second is at the top of the screen. I want to disable this auto-scrolling from the RecyclerView, but I still want the user to be able to scroll, and I still want the second EditText to be focused on so the user can start typing. How can I achieve this?

I've already tried the following solutions:

  • https://stackoverflow.com/a/8101614/4077294, but with a RecyclerView.OnItemTouchListener. I called recyclerView.requestFocusFromTouch in onInterceptTouchEvent.

    • Behavior: Scrolled to the top of the tapped EditText all the time.
  • Clearing the focus from any EditText whenever it was focused on, via

    editText.setOnFocusChangeListener(new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, bool hasFocus) {
            if (hasFocus) {
                v.clearFocus();
            }
        }
    });
    
    • Behavior: The keyboard never showed up, and the RecyclerView still scrolled to the top.

Disabling scrolling altogether as in this question is not acceptable because I still want the user to be able to scroll.


Answer:

I ended up with this solution from @pskink:

recylerView.setLayoutManager(new LinearLayoutManager(this) {
    @Override
    public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect, boolean immediate) {
        return false;
    }
});

It seems to work perfectly, but @pskink has mentioned that this could have problems when using arrow keys. He's posted another solution here: https://pastebin.com/8JLSMkF7. If you have problems with the above solution, you may try the alternative solution at the link. For now, I'm sticking with the one I just posted here.

UPDATE

Since support-library v25.3.0 you should also override another requestChildRectangleOnScreen method in LayoutManager:

@Override
public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect, boolean immediate, boolean focusedChildVisible) {
    return false;
}

Question:

I have a RecyclerView which consists of a TextView and EditText, for the TextView the RecyclerView working perfectly fine with me, but for the EditText, if I enter value in first cell and keep on entering for other cell and scroll the entered value above will be not present.

public class Assesment_MarkcardAdapter extends RecyclerView.Adapter<Assesment_MarkcardAdapter.ContactViewHolder> {

    private String[] mDataset;

    public Assesment_MarkcardAdapter(String[] myDataset)
    {
        mDataset = myDataset;
    }

    private List<Assesment_cardinfo> contactList;
    private static String LOG_TAG = "Assesment_MarkcardAdapter";


    public Assesment_MarkcardAdapter(List<Assesment_cardinfo> contactList) {
        this.contactList = contactList;
    }


    @Override
    public int getItemCount() {
        return contactList.size();
    }

    @Override
    public void onBindViewHolder(ContactViewHolder contactViewHolder, int i)
    {

        mDataset = new String[contactList.size()];
        Assesment_cardinfo ci = contactList.get(i);
        contactViewHolder.studentname.setText(ci.getStudentname());
        contactViewHolder.studentid.setText(ci.getStudentid());
        contactViewHolder.grade.setText(ci.getGrade());
        contactViewHolder.improvement.setText(ci.getImprovements());
        contactViewHolder.grade.setTag(ci);
        contactViewHolder.improvement.setTag(ci);
        contactViewHolder.myCustomEditTextListener.updatePosition(i);
        contactViewHolder.myCustomEditTextListener2.updatePosition2(i);
        //contactViewHolder.grade.setText(mDataset[i]);
    }

    @Override
    public Assesment_MarkcardAdapter.ContactViewHolder onCreateViewHolder(ViewGroup viewGroup, int i)
    {
        View itemView = LayoutInflater.
                from(viewGroup.getContext()).
                inflate(R.layout.assesment_markcard, viewGroup, false);

        return new ContactViewHolder(itemView , new MyCustomEditTextListener(),new MyCustomEditTextListener2());
    }

    public static class ContactViewHolder extends RecyclerView.ViewHolder {

        public MyCustomEditTextListener myCustomEditTextListener;
        public MyCustomEditTextListener2 myCustomEditTextListener2;

        protected TextView studentname;
        protected TextView studentid;
        protected EditText grade;
        protected EditText improvement;


        public ContactViewHolder(View v, MyCustomEditTextListener myCustomEditTextListener, MyCustomEditTextListener2 myCustomEditTextListener2 ) {
            super(v);
            studentname = (TextView) v.findViewById(R.id.txt_student_name);
            studentid = (TextView) v.findViewById(R.id.txt_student_id);
            grade = (EditText) v.findViewById(R.id.edtxt_grade);
            this.myCustomEditTextListener = myCustomEditTextListener;
            grade.addTextChangedListener(myCustomEditTextListener);
            improvement = (EditText) v.findViewById(R.id.edtxt_improvement);
            this.myCustomEditTextListener2 = myCustomEditTextListener2;
            improvement.addTextChangedListener(myCustomEditTextListener2);

        }

    }
    private class MyCustomEditTextListener implements TextWatcher
    {
        private int position;

        public void updatePosition(int position)
        {
            this.position = position;
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3)
        {
            // no op
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3)
        {
            contactList.get(position).setGrade(charSequence.toString());
        }

        @Override
        public void afterTextChanged(Editable editable) {
            // no op
        }
    }

    private class MyCustomEditTextListener2 implements TextWatcher
    {
        private int position;

        public void updatePosition2(int position)
        {
            this.position = position;
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3)
        {
            // no op
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3)
        {
            contactList.get(position).setImprovements(charSequence.toString());
        }

        @Override
        public void afterTextChanged(Editable editable) {
            // no op
        }
    }
    public List<Assesment_cardinfo> getStudentLists()
    {
        return contactList;
    }
}

Answer:

I have faced the same problem.

holder.editQty.addTextChangedListener

When you're adding a Textwatcher to Edittext that was added to array of listeners so this is bad practice.

Either you have to remove all old listener with set null.

 holder.editQty.addTextChangedListener(null);
 holder.editQty.addTextChangedListener(new TextWatcher())

It will resolve the problem.

Question:

I have edit text items in RecyclerView. Everything works fine except in API 28. When it comes to testing in Android Pie devices, a single tap on an edit text item of a RecyclerView opens up the soft input keyboard but then the edit text loses the focus immediately and hence we are required to tap again on that edit text. Once we tap again on that edit text, it works as usual. But it is weird. Generally, edit text sustains the focus on the very first tap.

I have tried following solutions with no success

https://radhedubey.wordpress.com/2014/08/24/android-listview-with-edittext-loses-focus-when-the-keyboard-displays/

http://androidtechnicalblog.blogspot.com/2014/04/quick-trick-of-week-edittext-inside.html?m=1


Answer:

Use targetSdkVersion 27 instead of 28 or 29.

Question:

I have a list of elements that is editable: I can add/delete new elements to the list. Furthermore I can duplicate each Element - duplicated elements are appended to the end of the list. Each element is displayed with a corresponding EditText where users can input quantity of the given element. The Problem: After duplicating an Element E1, editing the quantity of E1 also changes quantity of E2.

Every ListItem looks like this: TextView(ElementTitle) / EditText(ElementQuantity) Everything works flawlessly on lists of many elements - until I use my "duplicate" function. I assume that the problem has something to do with the Recyclerview reusing the EditTextListeners. I am assigning these in onCreateViewHolder as described in this answer: https://stackoverflow.com/a/31860393/6551120.

I tried adding notifydatasetchanged() wherever I could imagine any value. In duplicatedSelected() I tried unregistering and clearing adapter and LayoutManager and creating a new Adapter - without any result.

This is the method that duplicates my elements (In ListActivity):

private void duplicateSelected(){
   List selectedItemPositions = mAdapter.getSelectedItems();
   for (int i = 0; i < selectedItemPositions.size(); i++) {
      int j =(int) selectedItemPositions.get(i);
      modulElements.add(modulElements.get(j));
   }
   mAdapter.notifyDataSetChanged();

In MyAdapter:

private class ModulElementEditTextListener implements TextWatcher {
        private int position;

        public void updatePosition(int position) {
            this.position = position;
        }

        //Other Override Methods cut out for simplicity    

        @Override
        public void afterTextChanged(Editable editable) {
            updatePosition(position);
            int timesMultiplied;
            if(editable.toString().equals("")){
                timesMultiplied=Integer.parseInt("0");
            }else{
                timesMultiplied = Integer.parseInt(editable.toString());
            }            

            modulElements.get(position)
                .setMultiplier(newModulElementMultiplier());
            modulElements.get(position)
                .getMultiplier().setTimesMultiplied(timesMultiplied);            
        }
    } 

Expected result when entering quantity for E1: Quantity for E1 changes

Actual result when entering quantity for E1: Quantity for E1 and E2 (And E3, E4,E5... when I duplicate multiple times) changes.

If I save the list of elements to a database and reopen it I can flawlessy edit quantity of E1 and it does NOT change quantity of E2 - as I would expect it to happen in the first case.

Every hint or idea welcome, thank you so much!


Answer:

You must implement the cloneable interface for your data model and modify this line

modulElements.add(modulElements.get(j).clone());

Now you have different objects in the list

Question:

I'm a newbie coding witch android studio and I try to save data on editText inside a recyclerview but data disappear or is duplicated in another editText.

Could someone help me please ?

Here is my code :

TaskActivity.java

    package com.example.davidsimon.appexploit.activities;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.opengl.EGLDisplay;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.example.davidsimon.appexploit.R;
import com.example.davidsimon.appexploit.classes.ReturnResponse;
import com.example.davidsimon.appexploit.classes.Task;
import com.example.davidsimon.appexploit.classes.TaskAdapter;
import com.example.davidsimon.appexploit.classes.TaskToSend;
import com.example.davidsimon.appexploit.classes.User;
import com.example.davidsimon.appexploit.services.JsonService;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

import static android.R.attr.button;
import static android.R.attr.title;

public class TasksActivity extends AppCompatActivity {

    private List<Task> taskList = new ArrayList<>();
    private RecyclerView recyclerView;
    public TaskAdapter mAdapter;
    Button GoPhoto;
    String user;

    JsonService service;
    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient client;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_tasks);
        Button uploadButton = (Button) findViewById(R.id.butUpload);
        GoPhoto = (Button) findViewById(R.id.butt_photo);
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(getString(R.string.base_url))
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        service = retrofit.create(JsonService.class);
        Button takePictureButton = (Button) findViewById(R.id.butt_photo);
        user = getIntent().getStringExtra("user");
        //imageView = (ImageView) findViewById(R.id.imageview);

        uploadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                TaskToSend task;
                List<TaskToSend> listTask = new ArrayList<>();
                for (int i = 0; i < mAdapter.getItemCount(); i++) {

                    task = new TaskToSend(mAdapter.getItem(i).getTitle(), String.valueOf(mAdapter.getItem(i).isState()), mAdapter.getItem(i).getComment(), user);

                    if (task.getState() == "true") {
                        task.setState("Fait");
                    } else {
                        task.setState("Non fait");
                    }

                    listTask.add(task);

                }

                service.saveTasks(listTask).enqueue(new Callback<ReturnResponse>() {

                    @Override
                    public void onResponse(Call<ReturnResponse> call, Response<ReturnResponse> response) {
                        Log.wtf("Fichier", "RĂ©ponse");
                    }

                    @Override
                    public void onFailure(Call<ReturnResponse> call, Throwable t) {
                        Log.wtf("Fichier", "Pas de réponse");
                    }
                });
                Intent TakstoUpload = new Intent(TasksActivity.this, UploadActivity.class);
                startActivity(TakstoUpload);
            }
        });

        takePictureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(intent, 0);
           }
        });




        service.getTasks().enqueue(new Callback<List<Task>>() {
            @Override
            public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {

                List<Task> listeTaches = response.body();
                Log.wtf("Nombre de taches", "Nombre de taches : " + listeTaches.size());
                Calendar c = Calendar.getInstance();
                int DayOfWeek = c.get(Calendar.DAY_OF_WEEK);
                for (Task t : listeTaches) {
                     if (t.getPeriod()== DayOfWeek || t.getPeriod()== 0) {
                        taskList.add(t);
                    }
                }
                displayRecyclerView();
            }


            @Override
            public void onFailure(Call<List<Task>> call, Throwable t) {
                Log.wtf("GetTasks Failure", t.toString());
            }
        });


        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
    }


    public void displayRecyclerView() {
        recyclerView = (RecyclerView) findViewById(R.id.tasks_recycler_view);
        mAdapter = new TaskAdapter(taskList);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(mAdapter);

    }


    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    public Action getIndexApiAction() {
        Thing object = new Thing.Builder()
                .setName("Tasks Page") // TODO: Define a title for the content shown.
                // TODO: Make sure this auto-generated URL is correct.
                .setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
                .build();
        return new Action.Builder(Action.TYPE_VIEW)
                .setObject(object)
                .setActionStatus(Action.STATUS_TYPE_COMPLETED)
                .build();
    }

    @Override
    public void onStart() {
        super.onStart();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client.connect();
        AppIndex.AppIndexApi.start(client, getIndexApiAction());
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        AppIndex.AppIndexApi.end(client, getIndexApiAction());
        client.disconnect();
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            Bitmap mImageBitmap = (Bitmap) extras.get("data");

        }

    }



    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

Here my adapter TaskAdapter :

package com.example.davidsimon.appexploit.classes;

import android.content.Context;
import android.graphics.Movie;
import android.support.v7.widget.ListViewCompat;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;

import com.example.davidsimon.appexploit.R;
import com.example.davidsimon.appexploit.activities.TasksActivity;

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

import static android.R.attr.data;
import static android.R.attr.value;
import static com.example.davidsimon.appexploit.R.id.checkBox;

/**
 * Created by David SIMON on 22/08/2016.
 */
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.MyViewHolder> {


    private List<Task> TaskList;


    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView title;
        public CheckBox checkBox;
        public EditText finalComment;

        public MyViewHolder(View view) {
            super(view);
            title = (TextView) view.findViewById(R.id.title);
            checkBox = (CheckBox) view.findViewById(R.id.checkBox);
            finalComment = (EditText) view.findViewById(R.id.FinalComment);
            TextWatcher textWatcher = 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) {
                    int position = (int) finalComment.getTag();
                    TaskList.get(position).setComment(charSequence.toString());
                }

                @Override
                public void afterTextChanged(Editable editable) {


                }
            };
            finalComment.addTextChangedListener(textWatcher);
        }
    }


    public TaskAdapter(List<Task> TaskList) {

        this.TaskList = TaskList;
    }



    @Override
    public TaskAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recyvlerview, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {



        Task task = TaskList.get(position);
        holder.title.setText(task.getTitle());
        holder.finalComment.setTag(position);
        holder.checkBox.setOnCheckedChangeListener(null);
        holder.checkBox.setChecked(task.isState());

        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                task.setState(b);
            }
        });

    }


    public Task getItem(int position){
        return TaskList.get(position);
    }

    @Override
    public int getItemCount() {
        return TaskList.size();
    }


}

And my Task.java

package com.example.davidsimon.appexploit.classes;

/**
 * Created by David SIMON on 05/08/2016.
 */
public class Task {

    String title;
    boolean state;
    String comment;
    int period;
    String type;

    public Task(String title, boolean state, String comment, String type, int period) {
        this.title = title;
        this.state = state;
        this.comment = comment;
        this.type = type;
        this.period = period;
    }

    @Override
    public String toString() {
        return "Title : "+ title +
                "\nState : " + state +
                "\nComment : " + comment +
                "\nPeriod : " + period +
                "\nType : " + type;
    }

    public String getTitle() {
        return title;
    }


    public void setTitle(String title) {
        this.title = title;
    }

    public void setState(boolean state) {
        this.state = state;
    }

    public boolean isState() {
        return state;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public int getPeriod() { return period; }

    public void setPeriod(int period) { this.period = period; }
}

I just want to save data in my EditText "finalcomment". I already search some similar problem but I think my level is too low.

Thanks in advance


Answer:

A RecyclerView will reuse your views. So whenever you scroll onBindViewHolder will be called. Within that method you need to setup the view with the correct data. You need to set the EditText in your onBindViewHolder which will likely require you to save the tex that has been entered. Here's an example of how you'd do that without the save logic:

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {



    Task task = TaskList.get(position);
    holder.title.setText(task.getTitle());
    holder.finalComment.setTag(position);

    // You need to save the entered text and then set it in onBindViewHolder
    holder.finalComment.setText(THE TEXT FOR THE EDIT TEXT);

    holder.checkBox.setOnCheckedChangeListener(null);
    holder.checkBox.setChecked(task.isState());

    holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            task.setState(b);
        }
    });

}

Question:

ok guys

i'm developing an android app which requires lots of edittext fields(so i put them into recyclerview for better ui performance)

firstly i encountered the input values on edittext fields are not saved so scrolling caused the lose of values in edittext field

i solved the problem by adding textwatcher to edittext fields and saving input data but now im encountering another problem: just try the following steps in proper order:

1- tap to some edittext input field(soft keyboard open ups simultaneously)
2- now scroll the recyclerview to other edittext fields (so edittext which you entering value into it, disappears from screen)
3- and try to input some words into it by keyboard

after these steps edittext which you edited doesnt contain any value.

instead, other randomly choosen edittext gains the value which you entered

probably recyclerview's reusing mechanism is causing it, not sure

i dont want to disable scrolling when soft keyboard opened to fix this possible behaviour/issue so is there another way to solve this problem?

EDIT:

public class SampleAdapter extends RecyclerView.Adapter{
private static List<String> mEditTextValues = new ArrayList<>();

public SampleAdapter(List<String> dataSet){
     mEditTextValues = dataSet;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    return new CustomViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.edittext,parent,false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    CustomViewHolder viewHolder = ((CustomViewHolder)holder);
    viewHolder.mEditText.setTag(position);
    viewHolder.mEditText.setText(mEditTextValues.get(position));
}
@Override
public int getItemCount() {
    return mEditTextValues.size();
}

public class CustomViewHolder extends RecyclerView.ViewHolder{
    private EditText mEditText;
    public CustomViewHolder(View itemView) {
        super(itemView);
        mEditText = (EditText)itemView.findViewById(R.id.editText);
        mEditText.addTextChangedListener(new TextWatcher() {
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
            public void afterTextChanged(Editable editable) {
                if(mEditText.getTag()!=null){
                    mEditTextValues.set((int)mEditText.getTag(),editable.toString());
                }
            }
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        });
    }
}

}


Answer:

If you want to stop editing random place, you can hide the soft keypad when the current editing edit text starts non-focusing.

Adapter.bindView

viewHolder.mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                if (b == false) {
                    hideKeyboard(view.getContext(), view);
                }
            }
        });

To hide the keypad

/**
 * To hide a keypad.
 *
 * @param context
 * @param view
 */
public static void hideKeyboard(Context context, View view) {
    if ((context == null) || (view == null)) {
        return;
    }
    InputMethodManager mgr =
            (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    mgr.hideSoftInputFromWindow(view.getWindowToken(), 0);
}