I'm new to Android development. I'm facing a dead end developing an app for a project. Please take some time and help me out.
The problem:
I am generating some EditText views nested in a LinearLayout using a for loop.
For example:
LinearLayout rootView = (LinearLayout) findViewById(R.id.rootview);
for (int i=0,j=10;i<j;i++) {
EditText et = new EditText(this);
rootView.addView(et);
et.setHint("EditText No. "+ i);
et.setId(i);
} // This code is for example purposes only.
Now, I can't seem to understand how I can set an addTextChangedListener on the EditText that is focused at a particular time and set that text on other EditTexts. Please tell me what approach should I adopt to achieve this. I tried my best to explain the problem; however, if there is still any ambiguity, feel free to comment and ask. I'm waiting for a solution to this problem.
In terms of screenshots:
What I have:
What I want:
I hope this clears things up!
**
EDIT:
Thanks to TylerSebastian for the solution. I got it to work. Here is the final code: (Inside OnCreate() method)
final LinearLayout rootView = (LinearLayout) findViewById(R.id.rootview);
for (int i=0,j=10;i<j;i++) {
final EditText et = new EditText(this);
rootView.addView(et);
et.setHint("EditText No. "+ i);
et.setId(i);
final TextWatcher textwatcher = 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) {
}
#Override
public void afterTextChanged(final Editable s) {
for (int i=0;i<10;i++){
EditText view = (EditText) findViewById(i);
if (view != et){
view.setText(s.toString());
}
}
}
};
et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
et.addTextChangedListener(textwatcher);
} else {
et.removeTextChangedListener(textwatcher);
}
}
});
}
**
I don't have access to a machine with AS on it atm so no guarantee that the following is bug-free, but this should point you in the right direction:
final LinearLayout rootLayout = ...;
// within your loop
et.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(final Editable s) {
for (int i = 0; i < rootLayout.getChildCount(); i++) {
View view = rootLayout.getChildAt(i);
if (view instanceof EditText && view != et) {
((EditText) view).setText(s.toString());
}
}
}
});
edit: so the above will cause an infinite loop - see my comment below
How about:
final LinearLayout rootLayout = ...;
// again, within your loop
TextWatcher textWatcher = 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(final Editable s) {
for (int i = 0; i < rootLayout.getChildCount(); i++) {
View view = rootLayout.getChildAt(i);
if (view instanceof EditText && view != et) {
((EditText) view).setText(s.toString());
}
}
}
};
et.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
((EditText) view).addTextChangedListener(textWatcher);
} else {
((EditText) view).removeTextChangedListener(textWatcher);
}
}
});
basically, only the focused element will have the textwatcher
first add a LinearLayout in your XML like that
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
then create a new class
public class EditTextCust extends RelativeLayout {
EditText status;
public EditTextCust(Context context, Model post, int inputType,TextWatcher textWatcher) {
super(context);
inflate(context, R.layout.edit_text_cust, this);
status = (EditText) findViewById(R.id.editText);
status.setInputType(inputType);
post.setData(status.getText().toString());
status.setHint(post.getHint());
status.addTextChangedListener(textWatcher);
}
public String getText() {
return status.getText().toString();
}
public EditTextCust(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextCust(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
and creat new XML file names edit_text_cust for this custom view class
<EditText
android:id="#+id/dateEditText"
android:layout_width="match_parent"
android:background="#android:color/transparent"
android:padding="#dimen/_5sdp"
android:layout_height="match_parent"
android:textSize="#dimen/_12sdp" />
and creat model class to set your data
public class Model {
String hint;
String id;
String data;
public String getHint() {
return hint;
}
public void setHint(String hint) {
this.hint = hint;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
and in your class inside the for loop but this code
Model model = new Model();
model.setHint("HINT");
model.setId("1");
editTextCust = new EditTextCust(this, editTextCustModel, InputType.TYPE_CLASS_NUMBER, 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) {
// getText from here use
s.toString();
}
#Override
public void afterTextChanged(Editable s) {
}
});
linearLayout.addView(editTextCust);
it's work with me correctly, and if you didn't understand any thing from this code just add comment and i will help you :)
Related
I have recyclerView where i have added a editText. But when I type text to one edittext, text shows another edittext too. Here is the image..
Above image, I type 100 to other item, but it also shows in Settlements
Here is my adapter:
public class AdapterSectionRecycler extends SectionRecyclerViewAdapter<SectionHeader, Child, SectionViewHolder, ChildViewHolder> {
Context context;
private final OnItemClickListener listener;
public interface OnItemClickListener {
void onItemClick(Child child,Boolean isChecked);
}
public AdapterSectionRecycler(Context context, List<SectionHeader> sectionItemList,OnItemClickListener listener) {
super(context, sectionItemList);
this.context = context;
this.listener = listener;
}
#Override
public SectionViewHolder onCreateSectionViewHolder(ViewGroup sectionViewGroup, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.section_item, sectionViewGroup, false);
return new SectionViewHolder(view);
}
#Override
public ChildViewHolder onCreateChildViewHolder(ViewGroup childViewGroup, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_layout, childViewGroup, false);
return new ChildViewHolder(view);
}
#Override
public void onBindSectionViewHolder(SectionViewHolder sectionViewHolder, int i, SectionHeader sectionHeader) {
Log.e("name section--",sectionHeader.getSectionText());
sectionViewHolder.name.setText(sectionHeader.getSectionText());
}
#Override
public void onBindChildViewHolder(ChildViewHolder childViewHolder, int i, int i1, Child child) {
childViewHolder.chk_answer.setText(child.getAnswerName());
childViewHolder.tv_surveyAnswerId.setText(String.valueOf(child.getAnswerId()));
childViewHolder.chk_answer.setChecked(false);
childViewHolder.etPercentage.setImeOptions(EditorInfo.IME_ACTION_DONE);
childViewHolder.etsl.setVisibility(View.GONE);
childViewHolder.chk_answer.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
listener.onItemClick(child,true);
}else{
listener.onItemClick(child,false);
}
}
});
childViewHolder.etPercentage.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) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
}
Here is my Child View holder
public class ChildViewHolder extends RecyclerView.ViewHolder {
CheckBox chk_answer;
EditText etPercentage;
EditText etsl;
TextView tv_surveyAnswerId;
public ChildViewHolder(View itemView) {
super(itemView);
chk_answer = (CheckBox) itemView.findViewById(R.id.chk_answer);
etPercentage = (EditText) itemView.findViewById(R.id.etPercentage);
etsl = (EditText) itemView.findViewById(R.id.etsl);
tv_surveyAnswerId = (TextView) itemView.findViewById(R.id.tv_surveyAnswerId);
}
}
I call from activity:
AdapterSectionRecycler adapterSectionRecycler = new AdapterSectionRecycler(this, sections, new AdapterSectionRecycler.OnItemClickListener() {
#Override
public void onItemClick(Child child, Boolean isChecked) {
}
});
recyclerView_land_conversion.setAdapter(adapterSectionRecycler);
What is the wrong with my code? Please help me..
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());
}
}
});
}
This is from the Main Activity class. I have an arraylist of arrays and need to create a search bar for the listview.
adapter = new ArrayAdapter<String[]>(this, R.layout.list_view, android.R.id.text1, spellList)
{
public View getView(int position, View convertView, ViewGroup parent)
{
View view = super.getView(position, convertView, parent);
String[] entry = spellList.get(position);
TextView text1 = (TextView) view.findViewById(android.R.id.text1);
TextView text2 = (TextView) view.findViewById(android.R.id.text2);
text1.setText(entry[0]);
text2.setText(entry[1]);
return view;
}
};
wizList.setAdapter(adapter);
searchText.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) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
This is the data in an Arraylist of string arrays. Prefered if searched by the spell name.
final ArrayList<String[]> spellList;
public WizardDatabase()
{
spellList = new ArrayList<>();
spellList.add(new String[] { "Resistance", "Subject gains +1 on saving throws."});
spellList.add(new String[] { "Acid Splash", "Orb deals 1d3 acid damage."});
spellList.add(new String[] { "Detech Poison", "Detects poison in one creature or small object."});
public ArrayList<String[]> getList()
{
return spellList;
}
thanks.
If it's simple String search only then use the following code
searchText.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) {
}
#Override
public void afterTextChanged(Editable s) {
if (s.length() > 3) { // it's for performance I've put 3 you can change it
adapter.getFilter().filter(s.toString());
}
}
});
In an attempt to write a bit less code every time I wanted a SeekBar and a corresponding TextView showing it's numerical value, I wrote the following abstract class:
abstract public class SeekBarWrapper {
SeekBar bar;
TextView valueText;
int value = 0;
int minValue;
int divisor;
public SeekBarWrapper(SeekBar sb, TextView tv, int value, int minValue,
int divisor){
this.bar = sb;
this.valueText = tv;
this.value = value;
this.minValue = minValue;
this.divisor = divisor;
setListener();
}
private void setListener(){
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) { }
#Override
public void onStartTrackingTouch(SeekBar seekBar) { }
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(!fromUser) return;
value = progress + minValue;
valueText.setText(Integer.toString(value/divisor));
sendValue();
}
});
}
abstract protected void sendValue();
public void updateValue(int newValue){
if(newValue == value) return;
value = newValue;
valueText.setText(Integer.toString(value));
bar.setProgress(value*divisor-minValue);
}
}
For each concrete SeekBar I'll write a nested class, for example:
class VolumeBarWrapper extends SeekBarWrapper{
public VolumeBarWrapper(SeekBar s, TextView t, int v, int min, int div){
super(s, t, v, min, div);
}
public void sendValue(){
someCallback.volume(this.value);
}
}
And instantiate like so:
VolumeBarWrapper volume;
// later:
volume = new VolumeBarWrapper((SeekBar) view.findViewById(R.id.volume_bar),
(TextView) view.findViewById(R.id.volume_value), 300, 0, 70);
It's functional, and seemingly an improvement. What I would like to know:
Is there is some way to make this an anonymous inner class, or another method to further condense the per-instance code?
And less pressingly:
Am I abusing the "wrapper" label, doesn't it have some specialized meaning in pattern-speak?
Is this design "bad" from an OOP perspective (I'm still trying to school myself in this regard)?
You can always make a better SeekBar , and use it everywhere:
public class VersatileSeekBar extends SeekBar implements SeekBar.OnSeekBarChangeListener {
private TextView mTextView;
private ChangeHandler mChangeHandler;
public void bindDisplayToChange(TextView textView,ChangeHandler handler) {
mTextView = textView;
mChangeHandler = handler;
}
public VersatileSeekBar(Context context) {
super(context);
init();
}
public VersatileSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public VersatileSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if(mChangeHandler != null && mTextView != null){
mChangeHandler.onChange(i,mTextView);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
private void init(){
this.setOnSeekBarChangeListener(this);
}
public static abstract class ChangeHandler{
public abstract void onChange(int value,TextView textView);
}
}
Code to call :
myVersatileSeekBar.bindDisplayToChange(myTextView, new VersatileSeekBar.ChangeHandler() {
#Override
public void onChange(int value, TextView textView) {
textView.setText("level :" + value * 100);
}
});