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) {}
});
}
}
}
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);
}
It sounds like you need a ScrollView in your layout but there is no code posted
Try to put your TextWatcher in onBindViewHolder it will work
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
CustomViewHolder viewHolder = ((CustomViewHolder)holder);
viewHolder.mEditText.setText(mEditTextValues.get(position));
viewHolder.mEditText.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void afterTextChanged(Editable editable) {
}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
mEditTextValues.set(position,mEditText.getText().toString())
}
});
}
Related
I have a recyclerview in my android project and in the recyclerview im populating the name of the any items and it have EditText corresponding to every name view inside recyclerview, which means the person can edit the price of each item inside recyclerview.
Now outside recyclerview i have a button which when clicked a POST request is called and the names and their corresponding prices are updated.
I can't find a way by which i get all the data from recyclerview back to my fragment.
My sample code to understand the problem
public class TestsListAdapterLabsInside extends RecyclerView.Adapter<TestsListAdapterLabs.MyHolder> {
Context context;
ArrayList<TestListLabRetro> arrayList;
double[] TOTAL;
public TestsListAdapterLabsInside(Context context, ArrayList<TestListLabRetro> arrayList) {
this.context = context;
this.arrayList = arrayList;
this.TOTAL = new double[arrayList.size()];
}
#NonNull
#Override
public TestsListAdapterLabs.MyHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_test_labs2, viewGroup, false);
return new TestsListAdapterLabs.MyHolder(v);
}
#Override
public void onBindViewHolder(#NonNull app.dezignoo.knockadoc.Adapters.TestsListAdapterLabs.MyHolder myHolder, final int i) {
myHolder.name.setText(arrayList.get(i).getName());
myHolder.slno.setText(String.valueOf(i + 1));
myHolder.price.setText(arrayList.get(i).getPrice());
}
#Override
public int getItemCount() {
return arrayList.size();
}
public class MyHolder extends RecyclerView.ViewHolder {
TextView slno, name;
TextView price;
public MyHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.testName);
slno = itemView.findViewById(R.id.slno);
price = itemView.findViewById(R.id.testPrice);
}
}
}
this Adapter is defined below my fragment.
I want a final list of all the <name, price> from the recyclerview in my fragment to update to the server.
Thankyou in advance.
Step 1) First you need to add a textChangeListner on your editText and update your arrayList in it
myHolder.editText.addTextChangedListener(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) {
}
#Override
public void afterTextChanged(Editable editable) {
TestListLabRetro testListLabRetro = arrayList.get(i);
testListLabRetro.setPrice(editable.toString());
arrayList.set(i, testListLabRetro);
}
});
Step 2) Create a getData Method
public ArrayList<TestListLabRetro> getData(){
return this.arrayList;
}
Step 3) call getData method from your adapter where you are making a POST request to get updated arrayList
After your POST request, add the data to the ArrayList list and call adapter.notifydatasetchaged()
Hello i`m trying to get recyclerview viewholder at particular position with this code:
val viewHolder = educationRv.findViewHolderForAdapterPosition(i) as SectionsRecyclerAdapter.ViewHolder
the problem is that recycler view recycle not visible items and i can't get item and position 0 if its not visible. I searched before ask i tried this solutions, but can't prevent recycling of the views (i know that this is not good solution but i`m stuck and can't figure it out better) :
educationRv.recycledViewPool.setMaxRecycledViews(1,0)
override fun getItemViewType(position: Int): Int {
return 1
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
if (holder != null) {
holder.setIsRecyclable(false)
}
Generalized -> i have recyclerview with 20 edittexts which can be added dynamically, when user click save i need to get all edittexts values and save it to array, the problem comes when button save is clicked only two or three views are visible when i try to get not visible return null
As i got your query this solution would definitely help you
In you viewHolder do like this
etText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
yourEditTextList.set(getAdapterPosition(), s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
btnAddNewEditText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
yourEditTextList.add(new String(""));
notifyDataSetChanged();
}
});
Here yourEditTextList is the list of String in of your editText in your recylerView
In your activity where you have recylerView
btnDone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Fetch you list that your have passed on recycler view you will get here
}
});
I am making a notes app and my notes are autosaved to Firebase Database. So far a user can make their own notes but cannot edit them. I want the app to open the same note (meaning the title and desc fields will hold the data entered last time) if clicked so they can edit it but don't know how, I don't even know what to look for online as this is my first project.
New note creation & autoupdate
(One listener for title and one for body)
public class NewNoteActivity extends AppCompatActivity{
private EditText editText, etd;
private FirebaseAuth fAuth;
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference()/* THIS!*/.child("Users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("posts").push();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_note);
editText = findViewById(R.id.etx);
etd = findViewById(R.id.etdx);
final Map<String, Object> map = new HashMap<>();
map.put("id", databaseReference.getKey());
editText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
map.put("title", editText.getText().toString());
databaseReference.setValue(map);
}
});
etd.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
map.put("desc", etd.getText().toString());
databaseReference.setValue(map);
}
});
}
Display the notes
(and set onClick action)
adapter = new FirebaseRecyclerAdapter<Model, ViewHolder>(options) {
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
#Override
protected void onBindViewHolder(final ViewHolder holder, final int position, final Model model) {
holder.setTxtTitle(model.getmTitle());
holder.setTxtDesc(model.getmDesc());
//holder.setmId(model.getmId());
holder.root.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Here I need to find somehow to get back to the note I clicked on
}
});
}
};
recyclerView.setAdapter(adapter);
This is how the list looks
Since I'm not able to post images yet: https://i.imgur.com/MDQ15a6.png
Each block is a note. (Ignore the B)
I am trying to implement a list of edittext inside a listview. I have successfully added that by adding dynamically view inside a vertical linearlayout. Now i need to get the values from every edittext values from each main list item. Please check the image below
image file
Below is the code i am using to add dynamic edittext to the vertical linearlayout
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView != null){
return convertView;
}
convertView = LayoutInflater.from(context).inflate(R.layout.item,parent,false);
final LinearLayout subItem = convertView.findViewById(R.id.lvSubItem);
subItem.removeAllViews();
for (final Faltu faltu : posms.get(position).getFaltus()){
View subView = LayoutInflater.from(context).inflate(R.layout.subitem,null);
final EditText subEditText = subView.findViewById(R.id.subItem);
subItem.addView(subView);
subEditText.setTag(subItem.indexOfChild(subView));
return convertView;
}
I have tried with adding textChangedListener to the editext inside the for loop and onTextChanged i haved updated my value list with the text. But unfortunately it updates all values with same value.
subEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
subEditText.requestFocus();
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (s.length() > 0){
posms.get(position).getFaltus().get((Integer) subEditText.getTag()).setNumber(s.toString());
}
}
});
Any suggestion is appreciaed
Try using these lines of code
for (int i = 0; i < posms.get(position).getFaltus().size(); i++) {
final Faltu faltu = posms.get(position).getFaltus().get(i);
View subView = LayoutInflater.from(context).inflate(R.layout.subitem, null);
final EditText subEditText = subView.findViewById(R.id.subItem);
subItem.addView(subView);
subEditText.setTag(i);
subEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
subEditText.requestFocus();
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (s.length() > 0){
//posms.get(position).getFaltus().get(i).setNumber(s.toString());
faltu.setNumber(s.toString());
}
}
});
}
I'm trying to highlight my selected item in recyclerView when it's clicked.But it triggers two items instead. Please help me. Should i store clicked items as arraylist and clear them on new one clicked?
public class StationsAdapter extends RecyclerView.Adapter<StationsHolder> {
List<Station> stations;
public StationsAdapter(List<Station> stations){
this.stations = stations;
}
public void changeItemAtPosition(int position) {
notifyItemChanged(position);
}
#Override
public StationsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new StationsHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.stations_item,parent,false));
}
#Override
public void onBindViewHolder(StationsHolder holder, int position) {
bind(holder);
}
private void bind(final StationsHolder holder) {
holder.tvTitle.setText(stations.get(holder.getAdapterPosition()).getName());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.tvTitle.setTextColor(ContextCompat.getColor(AppDelegate.getContext(),R.color.colorAccent));
}
});
}
#Override
public int getItemCount() {
return stations.size();
}
}
This is due to recycler reusing the same view when you scroll. In order to fix that, you will have to do the next:
Store the selected item when you click on it. In a variable or in an array if you want more than one item
Check the selected item variable/array in the bind method to know if you have to color it or not
That way it will work flawlessly