I'm trying to add some results from a quiz so that when user gets each right answer it adds 1 to it but the code below never gives me the right answer the 'correctAns = correctAns+1'gives me all 5 at once, if I make the correctAns as local variable this will give me 1 for every right answer but it will NOT add up. Can any one please help.
public class AdapterListView extends ArrayAdapter<Questions> {
private int correctAns = 0;
public AdapterListView(Context context, int resource, ArrayList<Questions> questionsArrayList) {
super(context, resource);
this.mContext = context;
this.setQuestionsArrayList(questionsArrayList);
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
....
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
...
holder.editText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
if (holder.editText.getText().toString().trim().length() > 0) {
int inputNum = Integer.parseInt(String.valueOf(holder.editText.getText().toString().trim()));
if (getAnswersList().get(position) != inputNum) {
holder.imgFalse.setVisibility(View.VISIBLE);
holder.imgTrue.setVisibility(View.GONE);
} else {
correctAns = correctAns+1;
holder.imgTrue.setVisibility(View.VISIBLE);
holder.imgFalse.setVisibility(View.GONE);
}
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
return convertView;
}
static class ViewHolder {
TextView questionTextView;
EditText editText;
ImageView imgTrue, imgFalse;
}
}
You should increase the value of variable n
Replace
setCorrectAns(++n);
With this
n=n+1;
Related
I have a listview consists of TextView, EditText and Checkbox. I am want to make the state of the edittext to be persistent so that, when i change the text
inside the edittext and then scroll the listview up or down that text that was added/written into the edittext should not be changed and must remain as it is
I managed to make the checkbox persistent, I do not know how to make the edittext state persistent.
please have a look at the getView() methos it is posted below
and please let me know how to solve this issue
getView
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = null;
if (convertView == null) {
LayoutInflater layoutinflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
view = layoutinflater.inflate(R.layout.model, null);
final ViewHolder holder = new ViewHolder();
holder.tv = (TextView) view.findViewById(R.id.tv);
holder.cb = (CheckBox) view.findViewById(R.id.cb);
holder.et = (EditText) view.findViewById(R.id.et);
holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
ItemDesign element = (ItemDesign) holder.cb.getTag();
element.setChecked(buttonView.isChecked());
}
});
view.setTag(holder);
holder.cb.setTag(designList.get(position));//checkbox
//edittext
ItemDesign element = (ItemDesign) holder.et.getTag();
if (element != null) {
element.setEtTxt(holder.et.getText().toString());
}
holder.et.setTag(designList.get(position));
holder.tv.setTag(designList.get(position));//textview
} else {
view = convertView;
((ViewHolder)view.getTag()).et.setTag(designList.get(position));//edittext
((ViewHolder)view.getTag()).tv.setTag(designList.get(position));//textview
((ViewHolder)view.getTag()).cb.setTag(designList.get(position));//checkbox
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.tv.setText(designList.get(position).getTxt()); //textview
holder.cb.setChecked(designList.get(position).isChecked());//checkbox
//edittext
String etTxt = holder.et.getText().toString();
designList.get(position).setEtTxt(etTxt);
holder.et.setText(designList.get(position).getEtTxt());
return view;
}
private class ViewHolder {
TextView tv;
CheckBox cb;
EditText et;
}
You should add a TextWatcher to your edit text and use that to track the text inputted to the textview.
holder.et.setTag(designList.get(position));//edittext
holder.et.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) {
ItemDesign element = (ItemDesign) holder.cb.getTag();
element.setEditTextValue(s.toString())
}
if I understood you correctly, you need to register TextWatcher in your EditText and save string value every time, when you change text in it. So you will need to update you part of code from:
String etTxt = holder.et.getText().toString();
designList.get(position).setEtTxt(etTxt);
holder.et.setText(designList.get(position).getEtTxt());
to (sorry, I don't know what time of element do you have in designList, but let it be, for example, type Item, you can past your type instead of it):
final Item designItem = designList.get(position);
holder.et.setText(designItem.getEtTxt());
holder.et.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) {
designItem.setEtTxt(editable.toString);
}
});
But be careful. This solution is not working yet, since you have register new and new watchers but don't clear old. There is no perfect solution in this situation for me, since EditText doesn't have something like clearTextChangedListeners(). But you can solve it with introducing your own EditText (copied from here):
public class ExtendedEditText extends EditText {
private ArrayList<TextWatcher> mListeners = null;
public ExtendedEditText(Context ctx) {
super(ctx);
}
public ExtendedEditText(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
}
public ExtendedEditText(Context ctx, AttributeSet attrs, int defStyle) {
super(ctx, attrs, defStyle);
}
#Override
public void addTextChangedListener(TextWatcher watcher) {
if (mListeners == null) {
mListeners = new ArrayList<TextWatcher>();
}
mListeners.add(watcher);
super.addTextChangedListener(watcher);
}
#Override
public void removeTextChangedListener(TextWatcher watcher) {
if (mListeners != null) {
int i = mListeners.indexOf(watcher);
if (i >= 0) {
mListeners.remove(i);
}
}
super.removeTextChangedListener(watcher);
}
public void clearTextChangedListeners() {
if (mListeners != null) {
for (TextWatcher watcher : mListeners) {
super.removeTextChangedListener(watcher);
}
mListeners.clear();
mListeners = null;
}
}
}
After that final solution will look like this:
final Item designItem = designList.get(position);
holder.et.clearTextChangedListeners();
holder.et.setText(designItem.getEtTxt());
holder.et.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) {
designItem.setEtTxt(editable.toString);
}
});
Where et will be of type ExtendedEditText instead of EditText.
Hi I am using freeze concept in listview,
Row contains Textview and Edit texts,If i change any Edit text it should update the other column Textview is it possible? Currenly i am using https://github.com/InQBarna/TableFixHeaders Android library
Here is my adapter class:
When i change the age in edittext i need to change height based on age input.
public class FamilyNexusAdapter extends BaseTableAdapter {
private final int[] widths = { 100, 100, 100 };
private final float density;
private Vector<ProductMasterBO> items;
public FamilyNexusAdapter(Context context, Vector<ProductMasterBO> items) {
density = context.getResources().getDisplayMetrics().density;
this.items = items;
}
#Override
public int getRowCount() {
return this.items.size();
}
#Override
public int getColumnCount() {
return 3;
}
#Override
public View getView(final int row, int column, View convertView,
ViewGroup parent) {
String headerString[] = { "column 1", "column 2", "column 3",
};
if (row == -1) {
convertView = getLayoutInflater().inflate(
R.layout.item_table_header_first, parent, false);
((TextView) convertView.findViewById(R.id.product_name))
.setText(headerString[column + 1]);
} else{
user= (UserMaster) items.get(row);
if(column==-1){
txt=user.getuserName();
((TextView) convertView.findViewById(R.id.user_name))
.setText(headerString[column + 1]);
}else if(column==1){
txt=user.getage()+"";
EditText age = (EditText) convertView
.findViewById(R.id.age);
age.setText(txt);
age .addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
String ageString= s.toString();
if (!qty.equals("")) {
}}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
//i want to handle when i am trying to change age height should be change
}
});
}else if(column==2){
txt=user.getheight()+"";
((TextView) convertView.findViewById(R.id.user_name))
.setText(txt);
}
return convertView;
}
Use a viewHolder pattern and set the tag property of the EditText to refer the TextView.
I'm trying to create a listView with 2 editText on each row, that are using TextWatcher interface for recognizing if we changes the current text on the editText
My problem is that my adapter is very very laggy and slow. how can i handle this issue ?
here is my adapter:
public class AccountListInfoAdapter2 extends BaseAdapter {
private Activity mContext;
private ArrayList<ModelClass> accounts;
private DisplayImageOptions options;
private LayoutInflater inflater;
private prevClass mainActivityFragment;
private ViewHolder holder;
public AccountListInfoAdapter2(Activity activity, ArrayList<ModelClass> mAccountListData, prevClass mainActivityFragment) {
this.mContext = activity;
this.accounts = mAccountListData;
this.mainActivityFragment = mainActivityFragment;
inflater = LayoutInflater.from(mContext);
}
#Override
public int getCount() {
if (accounts == null) {
return 0;
} else
return accounts.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
view = inflater.inflate(R.layout.account_info_row, parent, false);
holder = new ViewHolder();
assert view != null;
setViews(view);
view.setTag(holder);
holder.emailAddress.setText(accounts.get(position).getEmail());
holder.fullName.setText(accounts.get(position).getFullName());
holder.fullName.setId(position);
holder.emailAddress.setId(position);
//Check if full name has been changed
holder.fullName.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) {
if (s.length() != count) {
if (!accounts.get(position).getFullName().equals(s.toString())) {
accounts.get(position).setFullName(s.toString());
}
}
}
#Override
public void afterTextChanged(Editable s) {
if (!accounts.get(position).getFullName().equals(s.toString())) {
accounts.get(position).setFullName(s.toString());
}
}
});
//Check if email name has been changed
holder.emailAddress.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) {
if(s.length() != count) {
if (!accounts.get(position).getEmail().equals(s.toString())){
accounts.get(position).getEmail(s.toString());
}
}
}
#Override
public void afterTextChanged(Editable s) {
if (!accounts.get(position).getEmail().equals(s.toString())) {
accounts.get(position).getEmail(s.toString());
}
}
});
return view;
}
public static class ViewHolder {
TextView emailAddress;
EditText fullName;
}
public void setViews(View view){
holder.emailAddress = (EditText) view.findViewById(R.id.accountInfoProfileEmailAddress);
holder.fullName = (EditText) view.findViewById(R.id.accountInfoFullName);
}
}
holder.fullName.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) {
if (s.length() != count)
{
if (!accounts.get(position).getFullName().equals(s.toString())) {
//accounts.get(position).setFullName(s.toString());
((MainActivity)context).changeListViewItem(position , s.toString);
}
}
}
#Override
public void afterTextChanged(Editable s) {
if (!accounts.get(position).getFullName().equals(s.toString())) {
//accounts.get(position).setFullName(s.toString());
((MainActivity)context).changeListViewItem(position , s.toString);
}
}
});
Add this function on main activity
public void changeListViewItem(int position , String text)
{
Log.e("" , ""+position);
Log.e("" , ""+text);
refreshAdapter();
}
1.addTextChangedListener can be add repeat.
U can try to add a log in onTextChanged.
Watch how many times it logs when u type a char.
When u use addTextChangedListener, add a tag.
2.U should try to use ViewHolder to help u.
I have list item with EditText in it, I dont know how many items there will be. I have a problem when I enter some text in EditText, and then scroll down a ListView, after I've scroll up again there is no text in my first EditText, or there is some text from other EditText from ListView.
Code :
public class MatHangAdapter
extends ArrayAdapter<MatHangModel> {
private static final int LAYOUT_ITEM_MAP_DOWNLOAD = R.layout.item_mat_hang;
private final LayoutInflater mInflater;
Context context;
public MatHangAdapter(final Context context) {
super(context,
LAYOUT_ITEM_MAP_DOWNLOAD,
new CopyOnWriteArrayList<MatHangModel>());
this.mInflater = LayoutInflater.from(context);
this.context = context;
}
/**
* input data from outside.
*/
public void fillData(List<MatHangModel> dataModels) {
this.clear();
this.addAll(dataModels);
}
#Override
public long getItemId(final int position) {
return position;
}
#Override
public View getView(int position,
View convertView,
ViewGroup parent) {
final ViewHolder holder;
if (convertView != null) {
holder = (ViewHolder) convertView.getTag();
} else {
final View view =
this.mInflater.inflate(LAYOUT_ITEM_MAP_DOWNLOAD,
parent,
false);
holder = new ViewHolder(getContext(),
view);
view.setTag(holder);
convertView = view;
}
//fill data.
holder.fillData(this.getItem(position));
return convertView;
}
public static class ViewHolder {
private final Context mContext;
// Fields.
#InjectView(R.id.tv_scan_barcode)
TextView tvScanBarcode;
#InjectView(R.id.tv_qty_price)
TextView tvQtyPrice;
#InjectView(R.id.et_amount)
EditText etAmount;
public ViewHolder(Context context,
View view) {
ButterKnife.inject(this,
view);// Initialize UI controls.
mContext = context;
//apply fonts....
// CommonUtil.setFontForMainTitleTopicViewRecursive(tvItemMenu);
}
/**
* fill data.
*/
public void fillData(MatHangModel matHangModel) {
//fill data
if (matHangModel != null) {
tvScanBarcode.setText(CommonUtil.getStringData(matHangModel.getBracode()));
tvQtyPrice.setText(""+CommonUtil.getIntegerData(matHangModel.getPrice()));
etAmount.setText(""+CommonUtil.getIntegerData(matHangModel.getAmount()));
etAmount.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(final CharSequence charSequence,
int start,
int before, int count) {
}
#Override
public void onTextChanged(final CharSequence charSequence,
final int i,
final int i1,
final int i2) {
}
#Override
public void afterTextChanged(final Editable editable) {
}
});
}
}
#OnClick(R.id.tv_scan_barcode)
void onSceanBarcode(View view){
CommonUtil.showViewWithAnimation(Techniques.FadeIn,view);
}
}
}
It's happen because of the ListView recycling mechanism, you need to update your Adapter data with the new value of the EditTexts.
For better performance, you can do it inside afterTextChanged() of the TextWatcher( to update the data only when you finish editing the text):
#Override
public void afterTextChanged(final Editable editable) {
// update your model
// matHangModel.setAmount(Integer.parseInt(editable.toString()));
// update your adapter data with the new value of "matHangModel"
}
EDIT
1) Add an update method in your adapter:
public void updateItem(MatHangModel model, int position){
this.insert(model, position);
}
2) Change your fillData method to pass to position as param, because you'll need it in the update:
public void fillData(MatHangModel matHangModel, int position) {
//fill data
if (matHangModel != null) {
tvScanBarcode.setText(CommonUtil.getStringData(matHangModel.getBracode()));
tvQtyPrice.setText(""+CommonUtil.getIntegerData(matHangModel.getPrice()));
etAmount.setText(""+CommonUtil.getIntegerData(matHangModel.getAmount()));
etAmount.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(final CharSequence charSequence,
int start,
int before, int count) {
}
#Override
public void onTextChanged(final CharSequence charSequence,
final int i,
final int i1,
final int i2) {
}
#Override
public void afterTextChanged(final Editable editable) {
matHangModel.setAmount(Integer.parseInt(editable.toString())); // here you update your model data
updateItem(matHangModel, position); // here you update your adapter data
}
});
}
}
As you know, Android recycle the views in a ListView so the text you entered in the EditText may be lost if you don't store it.
In the onTextChanged method of the TextWatcher store the text you entered with something like matHangModel.setAmount(etAmount.getText().toString())
Try this:
#Override
public void onTextChanged(final CharSequence charSequence,
final int i,
final int i1,
final int i2) {
matHangModel.setAmount(charSequence.toString()); //if amount is int then parse value. In layout EditText set android:inputType="number"
android:ems="10"
}
I am using a custom list view which contains two Buttons Yes or No. When I clicked on No button, a layout containing an edit text will be displayed. There are more than 15 items in the list view. When I tried to type and save the value in the edittext of the 1st item using TextWatcher(), then the value is save for both 5th and 1st position ie, the same value is saving in both 1st and 5th position.
The code I am using is:
holder.subQuestionAnswer.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) {
questionsModel.get(position).getQuestion_subquestion().get(0).setAnswer(holder.subQuestionAnswer.getText()
.toString());
Log.e("value", "no_active<>"+position+"<>"+questionsModel.get(position).getQuestion_subquestion().get(0).getAnswer().toString());
}
});
}
How can i avoid this?
It is because of recycling of view. Please check the following adapter. Use the logic according to your needs.
public class MultiSelectionProductAdapter extends ArrayAdapter<ProductListBean> {
private Context context;
private ArrayList<ProductListBean> productList;
private ArrayList<ProductListBean> mOriginalValues;
private LayoutInflater li;
public MultiSelectionProductAdapter(Context ctx, int simpleListItem1,
ArrayList<ProductListBean> data) {
super(ctx, simpleListItem1, data);
this.context = ctx;
this.productList = data;
li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return productList.size();
}
#Override
public ProductListBean getItem(int position) {
return productList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = li.inflate(R.layout.component_inventory_prod_list, null);
holder = new ViewHolder();
holder.tvProductName = (TextView) convertView.findViewById(R.id.tvProductName);
holder.tvProdShortCode = (TextView) convertView.findViewById(R.id.tvShortName);
holder.tvLastOrderedQty = (TextView) convertView.findViewById(R.id.tvLastOrderedQty);
holder.etQty = (EditText) convertView.findViewById(R.id.etQty);
holder.parentRL = (LinearLayout) convertView.findViewById(R.id.parentRL);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final ProductListBean tempBean = productList.get(position);
holder.etQty.setId(position);
final String productName = tempBean.getProductName();
final String productCode = tempBean.getProductCode();
final String productShortCode = tempBean.getProductShortCode();
if (mSelectedProd != null && mSelectedProd.contains(productCode)) {
final int indexOfProd = mSelectedProd.indexOf(productCode);
holder.etQty.setText(mSelectedProducts.get(indexOfProd).getEnteredQty());
}
holder.tvProductName.setText(productName);
holder.tvProdShortCode.setText(productShortCode);
holder.tvLastOrderedQty.setText(tempBean.getLastOrderedQty());
holder.etQty.setText(tempBean.getEnteredQty());
holder.parentRL.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
holder.etQty.requestFocus();
}
});
holder.etQty.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) {
final int pos = holder.etQty.getId();
final String qty = holder.etQty.getText().toString();
if (qty.length() > 0) {
if (String.valueOf(qty.charAt(0)).equals("0")) {
holder.etQty.setError("Invalid Quantity");
holder.etQty.setText("");
} else {
productList.get(pos).setEnteredQty(holder.etQty.getText().toString());
}
} else {
productList.get(pos).setEnteredQty("");
}
}
});
return convertView;
}
static class ViewHolder {
TextView tvProductName, tvProdShortCode, tvLastOrderedQty;
EditText etQty;
LinearLayout parentRL;
}