Android list view change text when row is deleted - android

I have a ListView, which has an hidden button which become visible on user long click on row.
If someone clicks this button, the row is deleted.
My rows are composed by transactions, and in the same Activity i got a TextView displaying the amount.
When I add a transaction, my text is changed and the budget updated. My problem is updating it when an user clicks the button and deletes a row.
here is my adapter class
public class HomePageListAdapter extends ArrayAdapter<TRANSAZIONE> {
ArrayList<TRANSAZIONE> transazioni;
public HomePageListAdapter(Context context, int textViewResourceId,
ArrayList<TRANSAZIONE> objects) {
super(context, textViewResourceId, objects);
transazioni = objects;
}
TRANSAZIONE transazione;
NumberFormat formatter = new DecimalFormat("#0.00");
#Override
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.adapter_home_page_list, null);
TextView tvDesc = (TextView) view.findViewById(R.id.tvDescription);
TextView tvAmou = (TextView) view.findViewById(R.id.tvAmount);
final Button btnElimina = (Button) view.findViewById(R.id.btnElimina);
transazione = transazioni.get(position);
String dText = transazione.getDescription();
String aText = "";
if(transazione.getAmount() != null) {
aText = formatter.format(transazione.getAmount()) + " €";
if (transazione.getAmount() > 0) {
tvAmou.setTextColor(Color.GREEN);
} else {
tvAmou.setTextColor(Color.RED);
}
}
tvDesc.setText(dText);
tvAmou.setText(aText);
view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
btnElimina.setVisibility(View.VISIBLE);
return false;
}
});
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (btnElimina.getVisibility() == View.VISIBLE) {
btnElimina.setVisibility(View.GONE);
}
}
});
btnElimina.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
new TRANSAZIONE().Delete(TRANSAZIONE.class, getContext(), "where id = '" + transazioni.get(position).getId() + "'");
Toast.makeText(getContext(), "Transazione eliminata.", Toast.LENGTH_SHORT).show();
transazioni.remove(position);
notifyDataSetChanged();
} catch (Exception ex) {
Toast.makeText(getContext(), "Errore non gestito.", Toast.LENGTH_SHORT).show();
}
}
});
return view;
}
}
It works properly, and I have no problems updating my layout.
** And this is the method which updates my TextView's text and calls the Adapter. It's in the Activity**
public void LoadTotal() throws Exception {
#SuppressWarnings("unchecked")
ArrayList<TRANSAZIONE> transazioni = (ArrayList<TRANSAZIONE>) new TRANSAZIONE().SelectAll(TRANSAZIONE.class, getContext(), "");
Double totale = Settings.getLimitAmount();
//prendo solo quelle del mese corrente
if (transazioni.size() > 0) {
int numeroAggiornamento = Settings.getResettingDay();
Calendar today = Calendar.getInstance();
Calendar transactionDate = Calendar.getInstance();
Calendar lastChangeDate = Calendar.getInstance();
lastChangeDate.set(Calendar.DAY_OF_MONTH, numeroAggiornamento);
if (today.get(Calendar.DAY_OF_MONTH) < numeroAggiornamento) {
lastChangeDate.add(Calendar.MONTH, -1);
}
for (TRANSAZIONE t : transazioni) {
transactionDate.setTime(t.getDate());
if (transactionDate.compareTo(lastChangeDate) == -1) {
transazioni.remove(t);
} else {
totale += t.getAmount();
}
}
}
if (transazioni.size() == 0) {
transazioni.add(new TRANSAZIONE("Nessuna transazione per il mese in corso.", null, null));
}
HomePageListAdapter adapter = new HomePageListAdapter(getContext(), R.layout.adapter_home_page_list, transazioni);
lvTransactions.setAdapter(adapter);
tvBudget.setText(formatter.format(totale));
}
My problem is the following:
When I delete a row, it disappears from the list, but I can't intercept this in my Activity.
I need someway to call the method LoadTotal() when my row is deleted.
Any help will be appreciated.
Thanks all and sorry for my not perfect English.

The cleanest way of doing it is by using a DataSetObserver.
Inside your activity you have this object:
private DataSetObserver adapterObserver = new DataSetObserver() {
#Override
public void onChanged(){
// here you call your method
LoadTotal();
}
}
and then you register/unreguster this observer during onResume/onPause
#Override
public void onResume(){
super.onResume();
LoadTotal(); // update with latest values
adapter.registerDataSetObserver(adapterObserver);
}
#Override
public void onPause(){
super.onPause();
adapter.unregisterDataSetObserver(adapterObserver);
}
edit: some debug info for the op.
here is the code for notifyDataSetChanged() from BaseAdapter
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
and then inside DataSetObservable is simply looping through the list of observers
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
That means there's very little to actually go wrong there. But it's important to understand what is happening. So my suggestion is to put a breakpoint on all the method calls: onPause, onResume, onChanged and the line you call notifyDataSetChanged. And run it with the debugger, so you can see what is being called when and find out why it's not working.

In your adapter class
public class HomePageListAdapter extends ArrayAdapter<TRANSAZIONE> {
Context context;
ArrayList<TRANSAZIONE> transazioni;
public HomePageListAdapter(Context context, int textViewResourceId,
ArrayList<TRANSAZIONE> objects) {
super(context, textViewResourceId, objects);
transazioni = objects;
this.context=context;
}
TRANSAZIONE transazione;
NumberFormat formatter = new DecimalFormat("#0.00");
#Override
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.adapter_home_page_list, null);
TextView tvDesc = (TextView) view.findViewById(R.id.tvDescription);
TextView tvAmou = (TextView) view.findViewById(R.id.tvAmount);
final Button btnElimina = (Button) view.findViewById(R.id.btnElimina);
transazione = transazioni.get(position);
String dText = transazione.getDescription();
String aText = "";
if(transazione.getAmount() != null) {
aText = formatter.format(transazione.getAmount()) + " €";
if (transazione.getAmount() > 0) {
tvAmou.setTextColor(Color.GREEN);
} else {
tvAmou.setTextColor(Color.RED);
}
}
tvDesc.setText(dText);
tvAmou.setText(aText);
view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
btnElimina.setVisibility(View.VISIBLE);
return false;
}
});
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (btnElimina.getVisibility() == View.VISIBLE) {
btnElimina.setVisibility(View.GONE);
}
}
});
btnElimina.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
new TRANSAZIONE().Delete(TRANSAZIONE.class, getContext(), "where id = '" + transazioni.get(position).getId() + "'");
Toast.makeText(getContext(), "Transazione eliminata.", Toast.LENGTH_SHORT).show();
transazioni.remove(position);
notifyDataSetChanged();
} catch (Exception ex) {
Toast.makeText(getContext(), "Errore non gestito.", Toast.LENGTH_SHORT).show();
}
}
});
return view;
}
}
You can call the method of your activity like
((YourActivityName)context).LoadTotal();

Related

Getting focus of EditText inside RecyclerView

I'm implementing an application in which user can store Debit Cards and later they can use it by just entering the CVV number of the same card. I have used RecyclerView for all the items(Debit Cards) stored by the user. Everything is working fine, view is rendering all good and I have used LinearLayoutManager to show Horizontal scroll.
Now the problem which I am facing is whenever I try to enter CVV of any card as soon as I click on it the view gets shifted towards the last item of the list of Stored Cards, So if I'm having three cards stored in my list and I try to enter CVV for the first one the view is shifting directly to the third card but the focus remains on the first cards EditText. I don't know what's going on with the same. I'm sharing some code part for the same.
Setting adapter and defining horizontal scroll :-
recyclerAdapter = new RecyclerStoredCardAdapter(mContext, storedCards);
LinearLayoutManager layoutManager
= new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
storedCardListRecycler.setLayoutManager(layoutManager);
storedCardListRecycler.setVisibility(View.VISIBLE);
storedCardListRecycler.setAdapter(recyclerAdapter);
Sharing the screenshots with this so it will get clear. Any help would be appreciable. Thanks.
I have did this using ListView not with RecyclerView
But you can do with RecyclerView also.
Here is my used class demo.
SettingItemListViewAdapter.java
/**
* Created by vishalchhodwani on 18/10/16.
*/
public class SettingItemListViewAdapter extends BaseAdapter {
private final String TAG = "SettingItemListViewAdapter";
Context context;
List<SettingListViewItem> settingItemList;
OnMyClickListeners onMyClickListeners;
MyDatabaseAdapter myDatabaseAdapter;
public SettingItemListViewAdapter(Context context, List<SettingListViewItem> settingItemList) {
this.context = context;
this.settingItemList = settingItemList;
myDatabaseAdapter = new MyDatabaseAdapter(context);
}
public void setMyClickListener(OnMyClickListeners onMyClickListeners) {
this.onMyClickListeners = onMyClickListeners;
}
#Override
public int getCount() {
return settingItemList.size();
}
#Override
public Object getItem(int position) {
return settingItemList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.setting_listview_item, parent, false);
holder.settingListViewForm = (RelativeLayout) convertView.findViewById(R.id.settingListViewItem_form1);
holder.vrijeTekst = (EditText) convertView.findViewById(R.id.settingListViewItem_ed_virje_row1);
holder.kenteken = (EditText) convertView.findViewById(R.id.settingListViewItem_ed_kenketen_row1);
holder.checkRow = (ImageView) convertView.findViewById(R.id.settingListViewItem_check_row1);
holder.deleteRow = (ImageView) convertView.findViewById(R.id.settingListViewItem_deleteRow);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.vrijeTekst.setText(settingItemList.get(position).getItemVrijeTekst());
holder.kenteken.setText(settingItemList.get(position).getItemKenteken());
boolean isSelected = settingItemList.get(position).isItemSelected();
holder.checkRow.setImageResource(isSelected ? R.drawable.checked : R.drawable.uncheked);
holder.vrijeTekst.setTag(position);
holder.vrijeTekst.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(final View v, boolean hasFocus) {
try {
if (!hasFocus) {
if (settingItemList.size() > 0) {
int position = (int) v.getTag();
EditText Caption = (EditText) v;
settingItemList.get(position).setItemVrijeTekst(Caption.getText().toString());
}
} else {
EditText caption = (EditText) v;
caption.setCursorVisible(true);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
holder.kenteken.setTag(position);
holder.kenteken.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(final View v, boolean hasFocus) {
try {
if (!hasFocus) {
if (settingItemList.size() > 0) {
int position = (int) v.getTag();
EditText Caption = (EditText) v;
settingItemList.get(position).setItemKenteken(Caption.getText().toString());
}
} else {
EditText caption = (EditText) v;
caption.setCursorVisible(true);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
holder.checkRow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (myDatabaseAdapter.isAvailableInTable(settingItemList.get(position).getItemId()))
onMyClickListeners.onSelectButtonClicked(position);
}
});
holder.deleteRow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onMyClickListeners.onDeleteItemButtonClicked(position);
}
});
if (getCount() == position + 1) {
holder.vrijeTekst.requestFocus();
holder.vrijeTekst.performClick();
}
return convertView;
}
public static class ViewHolder {
RelativeLayout settingListViewForm;
EditText vrijeTekst, kenteken;
ImageView checkRow, deleteRow;
}
}
SettingN_New.java (It is a fragment)
public class SettingN_New extends Fragment implements OnClickListener, OnMyClickListeners {
private final String TAG = "SettingN_New";
Context context;
private TextView tv_demo;
ToggleButton togglebtn_save;
Button btn_save, btn_add;
ListView settingItemListView;
List<SettingListViewItem> settingItemList;
SettingItemListViewAdapter settingItemListViewAdapter;
MyDatabaseAdapter myDatabaseAdapter;
TinyDB loginpref;
boolean isNewRowAdded = true;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//This line of code will stay focus on selected edittext in list
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
ActionBar bar = getActivity().getActionBar();
bar.show();
View rootView = inflater.inflate(R.layout.setting_new, container, false);
initializeViews(rootView);
setUI();
getListOfItems();
return rootView;
}
private void setUI() {
try {
if (loginpref.getBoolean(ConstantLib.PREF_AUTO_LOGIN)) {
togglebtn_save.setChecked(true);
} else {
togglebtn_save.setChecked(false);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
private void initializeViews(View rootView) {
context = getActivity();
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View headerView = inflater.inflate(R.layout.setting_listview_header, null);
btn_save = (Button) headerView.findViewById(R.id.btn_save);
btn_add = (Button) headerView.findViewById(R.id.btn_add);
togglebtn_save = (ToggleButton) headerView.findViewById(R.id.togglebtn_save);
tv_demo = (TextView) headerView.findViewById(R.id.tv_demo);
settingItemList = new ArrayList<>();
settingItemListView = (ListView) rootView.findViewById(R.id.setting_listView);
settingItemListView.setClickable(true);
settingItemListView.refreshDrawableState();
settingItemListView.addHeaderView(headerView);
settingItemListView.setItemsCanFocus(true);
settingItemListViewAdapter = new SettingItemListViewAdapter(context, settingItemList);
settingItemListViewAdapter.setMyClickListener(this);
settingItemListView.setAdapter(settingItemListViewAdapter);
myDatabaseAdapter = new MyDatabaseAdapter(context);
loginpref = new TinyDB(getActivity());
btn_save.setOnClickListener(this);
btn_add.setOnClickListener(this);
tv_demo.setOnClickListener(this);
togglebtn_save.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
loginpref.putBoolean(ConstantLib.PREF_AUTO_LOGIN, isChecked);
}
});
}
private void getListOfItems() {
settingItemList.clear();
settingItemList.addAll(myDatabaseAdapter.getAllData());
if (settingItemList.size() == 0) {
isNewRowAdded = true;
SettingListViewItem settingListViewItem = new SettingListViewItem();
settingListViewItem.setItemId(settingItemList.size() + "");
settingListViewItem.setItemVrijeTekst("");
settingListViewItem.setItemKenteken("");
settingListViewItem.setItemSelected(false);
settingItemList.add(settingListViewItem);
} else {
isNewRowAdded = false;
}
notifyDataSetChanged();
}
private void hideKeyboard() {
// Check if no view has focus:
View view = getActivity().getCurrentFocus();
if (view != null) {
InputMethodManager inputManager = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(view.getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_save:
clearFocus();
hideKeyboard();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (isValidationSuccess())
saveAllData();
}
}, 200);
break;
case R.id.btn_add:
addAnotherRow();
break;
case R.id.tv_demo:
clickedOnTvDemo();
break;
}
}
private void clickedOnTvDemo() {
try {
Intent i = new Intent(getActivity(), Setting_exp_activity.class);
startActivity(i);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
private boolean isValidationSuccess() {
Log.e(TAG, "isValidationSuccess() called : settingItemList.size()==" + settingItemList.size());
for (int i = 0; i < settingItemList.size(); i++) {
if (settingItemList.get(i).getItemVrijeTekst().equalsIgnoreCase("") || settingItemList.get(i).getItemKenteken().equalsIgnoreCase("")) {
showToast("Veld mag niet leeg zijn");// showToast("Fields should not be empty!!");
return false;
}
}
return true;
}
private void saveAllData() {
Log.e(TAG, "saveAllData() called");
myDatabaseAdapter.clearTable();
for (int i = 0; i < settingItemList.size(); i++) {
isNewRowAdded = false;
SettingListViewItem settingListViewItem = new SettingListViewItem();
settingListViewItem.setItemId(i + "");
settingListViewItem.setItemVrijeTekst(settingItemList.get(i).getItemVrijeTekst());
settingListViewItem.setItemKenteken(settingItemList.get(i).getItemKenteken());
settingListViewItem.setItemSelected(settingItemList.get(i).isItemSelected());
myDatabaseAdapter.insertDataToTable(settingListViewItem);
}
DialogUtils.showInfoDialog(getActivity(),
"Instellingen opgeslagen");
}
private void addAnotherRow() {
Log.e(TAG, "addAnotherRow() called");
if (settingItemList.size() > 0 && !isNewRowAdded) {
if (!settingItemList.get(settingItemList.size() - 1).getItemVrijeTekst().equalsIgnoreCase("") && !settingItemList.get(settingItemList.size() - 1).getItemKenteken().equalsIgnoreCase("")) {
isNewRowAdded = true;
Log.e(TAG, "addAnotherRow() called check 1");
SettingListViewItem settingListViewItem = new SettingListViewItem();
settingListViewItem.setItemId(settingItemList.size() + "");
settingListViewItem.setItemVrijeTekst("");
settingListViewItem.setItemKenteken("");
settingListViewItem.setItemSelected(false);
settingItemList.add(settingListViewItem);
notifyDataSetChanged();
} else {
Log.e(TAG, "addAnotherRow() called check 2");
showToast("Al toegevoegd");// showToast("Already Added!!");
}
} else {
if (!isNewRowAdded) {
isNewRowAdded = true;
Log.e(TAG, "addAnotherRow() called check 3");
SettingListViewItem settingListViewItem = new SettingListViewItem();
settingListViewItem.setItemId("0");
settingListViewItem.setItemVrijeTekst("");
settingListViewItem.setItemKenteken("");
settingListViewItem.setItemSelected(false);
settingItemList.add(settingListViewItem);
notifyDataSetChanged();
} else {
Log.e(TAG, "addAnotherRow() called check 4");
showToast("Al toegevoegd");// showToast("Already Added!!");
}
}
settingItemListView.setSelection(settingItemList.size());
Log.e(TAG, "addAnotherRow() called check 5");
Log.e(TAG, "after settingItemList.size()==" + settingItemList.size());
}
#Override
public void onDeleteItemButtonClicked(int position) {
Log.e(TAG, "onDeleteItemButtonClicked() position==" + position);
if (myDatabaseAdapter.getAllData().size() > 0)
showAlertForDeleteItem(position);
else
showToast("Er is geen item te verwijderen"); // showToast("No item to Delete");
}
#Override
public void onSelectButtonClicked(int position) {
Log.e(TAG, "onSelectButtonClicked() position==" + position);
for (int i = 0; i < settingItemList.size(); i++) {
Log.e(TAG, "onSelectButtonClicked() called check 3");
settingItemList.get(i).setItemSelected(false);
}
settingItemList.get(position).setItemSelected(true);
notifyDataSetChanged();
}
private void showAlertForDeleteItem(final int position) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setMessage("Weet je zeker dat je dit item wilt wissen?");//alertDialog.setMessage("Are you sure you want to delete this item?");
// ja==yes
alertDialog.setPositiveButton("Ja", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
myDatabaseAdapter.deleteTableRow(settingItemList.get(position).getItemId() + "");
settingItemList.remove(position);
settingItemListViewAdapter.notifyDataSetChanged();
if (settingItemList.size() == position + 1) {
isNewRowAdded = false;
}
if (settingItemList.size() == 0) {
isNewRowAdded = false;
addAnotherRow();
}
}
});
//Annuleer==cancel
alertDialog.setNegativeButton("Annuleer", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.show();
}
private void notifyDataSetChanged() {
settingItemListViewAdapter.notifyDataSetChanged();
}
private void showToast(String message) {
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
public void clearFocus() {
if (getActivity().getWindow().getCurrentFocus() != null) {
getActivity().getWindow().getCurrentFocus().clearFocus();
}
}
}
I am giving you my whole class. why? Because it will give you more understanding that how I used it with ListView.
Test it and Let me know. :)
Note
This line of code is very important - getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
Not able to reproduce this issue. Let me know if the following code does what you are facing. If not, can provide more feedback if you share you Adapter's Code.
MainActivity.java
public class MainActivity
extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
MyAdapter adapter = new MyAdapter();
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
recyclerView.setAdapter(adapter);
}
}
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_ite, parent);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((EditText)((MyViewHolder)holder).mBinding.findViewById(R.id.editText)).setHint(position + " ");
}
#Override
public int getItemCount() {
return 100;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
View mBinding;
public MyViewHolder(View binding) {
super(binding);
this.mBinding = binding;
}
}
}
The 2xml layouts:
<EditText
android:id="#+id/editText"
android:layout_height="200dp"
android:layout_width="300dp"/>
</android.support.v7.widget.CardView>
My main_activity.xml is as follows:
<RelativeLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
</RelativeLayout>
As you can see this is the simplest case. Let me know if I missed anything.

How to increment TextView value outside ListView when ListView button is clicked in Android

I have a TextView outside ListView and i need to add prices when the plus button (ie,quantity is incremented )in ListView is clicked.In my program i am not able to add prices when new position ListView button is clicked.I need to find the total price to be payed by the customer when plus button is clicked in ListView
public class ListAdapter1 extends BaseAdapter {
public int qty=1;
public ArrayList<Integer> quantity = new ArrayList<Integer>();
private TextView total;
private String[] listViewItems,prices,weight;
TypedArray images;
public static int pValue;
private Context context;
public static boolean t=false;
CustomButtonListener customButtonListener;
public void setTextView(TextView total)
{
this.total = total;
}
public ListAdapter1(Context context, String[] listViewItems, TypedArray images, String[] weight, String[] prices) {
this.context = context;
this.listViewItems = listViewItems;
this.images = images;
this.prices=prices;
this.weight=weight;
}
public void setCustomButtonListener(CustomButtonListener customButtonListner)
{
this.customButtonListener = customButtonListner;
}
#Override
public int getCount() {
return 5;
}
#Override
public String getItem(int position) {
return listViewItems[position];
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View row;
final ListViewHolder listViewHolder;
if(convertView == null)
{
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.product,parent,false);
listViewHolder = new ListViewHolder();
listViewHolder.tvProductName = (TextView) row.findViewById(R.id.tvProductName)
listViewHolder.tvPrices = (TextView) row.findViewById(R.id.tvProductPrice);
listViewHolder.btnPlus = (ImageButton) row.findViewById(R.id.ib_addnew);
listViewHolder.edTextQuantity = (EditText) row.findViewById(R.id.editTextQuantity);
listViewHolder.btnMinus = (ImageButton) row.findViewById(R.id.ib_remove);
row.setTag(listViewHolder);
}
else
{
row=convertView;
listViewHolder= (ListViewHolder) row.getTag();
}
try{
listViewHolder.edTextQuantity.setText(quantity.get(position) );
}catch(Exception e){
e.printStackTrace();
}
listViewHolder.btnMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, " " + position, Toast.LENGTH_SHORT).show();
int mValue = Integer.parseInt(listViewHolder.edTextQuantity.getText().toString());
if (mValue <=0) {
System.out.println("not valid");
mValue=0;
listViewHolder.edTextQuantity.setText("" +mValue);
}
else{
pValue=pValue/mValue;
mValue--;
pValue=pValue*mValue;
total.setText(String.valueOf(pValue));
System.out.println("mvalue after reducing-----------"+mValue);
System.out.println("pvalue-----------"+pValue);
listViewHolder.edTextQuantity.setText( "" +mValue );
}
}
});
listViewHolder.btnPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, " " + position, Toast.LENGTH_SHORT).show();
int mValue = Integer.parseInt(listViewHolder.edTextQuantity.getText().toString());
pValue=Integer.parseInt(listViewHolder.tvPrices.getText().toString());
mValue++;
listViewHolder.edTextQuantity.setText("" + mValue);
System.out.println("mValue after increment---" + mValue);
pValue=pValue*mValue;
System.out.println("pvalue-----------"+pValue);
total.setText(String.valueOf(pValue));
}
});
return row;
}
I need to get total price when any of the ListView button is clicked.
First you need to store value in HashMap<> when user click the plus and minus button.
Then sum the all values in HashMap.
For Example
try{
int sum = 0;
for(HashMap<String, String> map : arrayList) {
sum += Integer.parseInt(map.get("mark"));
}
} catch (Exception e) {
//Manage your exception
}
// sum has the value for the marks total.
System.out.println("Total Marks: "+sum);
Refere my previous answer Here
For that you need to create interface which notify in activity where you want that count.
put snippet in adapter to initialize interface and setter.
public interface IEvent {
void onItemChange(int count);
}
private IEvent iEvent;
//setter method for interface
public void setQuanityEvent(IEvent ievent) {
this.lastPageHandler = handler;
}
put this code in btnMinus.setOnClickListener
//if ievent interface variable register via set
if (ievent != null) {
//pValue is quality COUNT you want to send outside listview.
ievent.onItemChange(pValue);
}
activity code after creating adapter instance
//ListAdapter1 adapter = new ListAdapter1(your params);
adapter.setQuanityEvent(new ListAdapter1.IEvent() {
#Override
public void onItemChange(int count) {
}
}
});

Multiple Countdown Timer in Expandable Listview Android not working

From last week I am trying to implement multiple countdown timer in expandable list view.I want to decrease time till 00:00:00 and according to that I need to update text in parent element of expandable list view.
My problem is :
1) on scrolling expandable list view timer restarts
2) on expand and collapse timer restarts
3) on event on child button i need to update particular position's text on parentview
One more thing I'm trying to implement is on clicking one button from child view I need to update text on parent view but i'm stucked there.
Here is my adapter containing both parent and child.
public class Sent_ListAdapter extends BaseExpandableListAdapter {
private Context _context;
**private List<SentModel> _listDataHeader;**
// child data in format of header title, child title
**private HashMap<SentModel, List<SentModel>> _listDataChild;**
private TextView txt_summary;
private TextView datetime_element;
private LinearLayout ll_arrowtorecord;
**private String[] ti;**
**private CountDownTimer cdt_sent;**
**private HashMap<TextView, CountDownTimer> counters;**
**private TextView deadline;**
public Sent_ListAdapter(Context context, List<SentModel> listDataHeader, HashMap<SentModel, List<SentModel>> listChildData) {
this._context = context;
this._listDataHeader = listDataHeader;
this._listDataChild = listChildData;
ll_end = new FrameLayout[_listDataHeader.size()];
ll_closeaceess = new FrameLayout[_listDataHeader.size()];
ll_whoaccpted = new LinearLayout[_listDataHeader.size()];
**this.counters = new HashMap<TextView, CountDownTimer>();**
}
#Override
public int getGroupCount() {
return this._listDataHeader.size();
}
#Override
public int getChildrenCount(int groupPosition) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition)).size();
}
#Override
public Object getGroup(int groupPosition) {
return this._listDataHeader.get(groupPosition);
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition)).get(childPosition);
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
final SentModel headerTitle = (SentModel) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.element_sentlist, null);
}
ll_arrowtorecord = (LinearLayout) convertView.findViewById(R.id.ll_arrowtorecord);
ll_arrowtorecord.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (headerTitle.getFile().trim().contains(".mp4")) {
Log.v("", TAG + "==video==" + headerTitle.getFile());
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
Uri data = Uri.parse(headerTitle.getFile());
intent.setDataAndType(data, "video/mp4");
startActivity(intent);
} else if (headerTitle.getFile().trim().contains(".jpg")) {
Log.v("", TAG + "==image==" + headerTitle.getFile());
Intent gotorecoedactivity = new Intent(context, RecordedAsset.class);
gotorecoedactivity.putExtra("image", headerTitle.getFile());
startActivity(gotorecoedactivity);
overridePendingTransition(R.anim.right_slide_in, R.anim.left_side_out);
finish();
} else {
Toast.makeText(context, "No recorded asset is there.", Toast.LENGTH_SHORT).show();
}
}
});
txt_summary = (TextView) convertView.findViewById(R.id.txt_summary);
if (headerTitle.get_desc().equalsIgnoreCase("") || headerTitle.get_desc() == null) {
txt_summary.setText(" Description");
} else {
txt_summary.setText(headerTitle.get_desc());
}
datetime_element = (TextView) convertView.findViewById(R.id.datetime_element);
final TextView tv = datetime_element;
deadline = (TextView) convertView.findViewById(R.id.deadline);
**if (headerTitle.getRemaining_completion_time().equalsIgnoreCase("") || headerTitle.getRemaining_completion_time() == null) {
datetime_element.setText("");
}
else if (headerTitle.getRemaining_completion_time().equalsIgnoreCase("00:00:00"))
{
tv.setText("Completion time over");
deadline.setVisibility(View.GONE);
}
else
{
ti = headerTitle.getRemaining_completion_time().split(":");
int hrs = Integer.parseInt(ti[0]);
cdt_sent = counters.get(datetime_element);
int days = Integer.parseInt(headerTitle.getRemaining_days());
// int hours1 = datetime_plus(days, Integer.parseInt(ti[0]));
int min = Integer.parseInt(ti[1]);
int sec = Integer.parseInt(ti[2]);
long d1 = TimeUnit.DAYS.toMillis(days);
long m1 = TimeUnit.MINUTES.toMillis(min);
long h1 = TimeUnit.HOURS.toMillis(hrs);
long s1 = TimeUnit.SECONDS.toMillis(sec);
final long milliseco = d1 + m1 + h1 + s1;
if (cdt_sent != null) {
cdt_sent.cancel();
cdt_sent = null;
}
cdt_sent = new CountDownTimer(milliseco, 1000)
{
int days = 0;
int hours1 = 0;
private String sDate;
int min = 0;
int sec = 0;
#Override
public void onTick(long millisUntilFinished)
{
millisUntilFinished -= (days * DateUtils.DAY_IN_MILLIS);
if (millisUntilFinished > DateUtils.HOUR_IN_MILLIS)
{
hours1 = (int) (millisUntilFinished / DateUtils.HOUR_IN_MILLIS);
}
millisUntilFinished -= (hours1 * DateUtils.HOUR_IN_MILLIS);
if (millisUntilFinished > DateUtils.MINUTE_IN_MILLIS)
{
min = (int) (millisUntilFinished / DateUtils.MINUTE_IN_MILLIS);
}
millisUntilFinished -= (min * DateUtils.MINUTE_IN_MILLIS);
if (millisUntilFinished > DateUtils.SECOND_IN_MILLIS)
{
sec = (int) (millisUntilFinished / DateUtils.SECOND_IN_MILLIS);
}
sDate = " " + String.format("%02d", hours1) + "h " + String.format("%02d", min) + "m " + String.format("%02d", sec) + "s ";
_listDataHeader.get(groupPosition).setTime(sDate);
String hms = String.format("%02d,%02d:%02d:%02d", TimeUnit.MILLISECONDS.toDays(milliseco),TimeUnit.MILLISECONDS.toHours(milliseco),
TimeUnit.MILLISECONDS.toMinutes(milliseco) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.MILLISECONDS.toSeconds(milliseco) % TimeUnit.MINUTES.toSeconds(1));
// Log.v("", "Bansi"+"==hms=="+hms);
tv.setText(_listDataHeader.get(groupPosition).getTime());
}
#Override
public void onFinish() {
tv.setText("Completion time over");
deadline.setVisibility(View.GONE);
}
};
counters.put(tv, cdt_sent);
cdt_sent.start();
}**
return convertView;
}
#SuppressLint("InflateParams")
#Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
final SentModel childText = (SentModel) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.element_childsent, null);
}
ll_whoaccpted[groupPosition] = (LinearLayout) convertView.findViewById(R.id.ll_whoaccpted);
ll_end[groupPosition] = (FrameLayout) convertView.findViewById(R.id.ll_end);
ll_closeaceess[groupPosition] = (FrameLayout) convertView.findViewById(R.id.ll_closeaceess);
txt_whoaccepted = (TextView) convertView.findViewById(R.id.txt_whoaccepted);
img_block = (ImageView) convertView.findViewById(R.id.img_block);
img_end = (ImageView) convertView.findViewById(R.id.img_end);
txt_end = (TextView) convertView.findViewById(R.id.txt_end);
txt_closeacess = (TextView) convertView.findViewById(R.id.txt_closeacess);
ll_whoaccpted[groupPosition].setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
showWhoAcceptedpopup(childText.getB_id(), groupPosition + "");
if (Utils.detectInternetConnection(context)) {
new post_WhoAccepted().execute(childText.getB_id(), groupPosition + "");
} else {
progressDialog.showWarningDialog_Click(getString(R.string.no_internet), new OnClickListener() {
#Override
public void onClick(View v) {
progressDialog.dialogDismiss();
try {
Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS);
startActivity(callGPSSettingIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
});
if (childText.getIs_cancel().equalsIgnoreCase("0")) {
ll_end[groupPosition].setBackgroundColor(Color.parseColor("#CBCBCB"));
txt_end.setTextColor(Color.parseColor("#7E7E7E"));
txt_end.setText("You ended the .");
txt_end.setGravity(Gravity.CENTER);
img_end.setImageResource(R.drawable.cross_circleclick);
ll_end[groupPosition].setClickable(false);
} else {
ll_end[groupPosition].setBackgroundColor(Color.parseColor("#650030"));
txt_end.setTextColor(Color.parseColor("#FF0101"));
txt_end.setText("End ");
txt_end.setGravity(Gravity.RIGHT);
img_end.setImageResource(R.drawable.cross_circle);
ll_end[groupPosition].setClickable(true);
if (endornot.get(groupPosition) == 0) {
} else {
ll_end[groupPosition].setBackgroundColor(Color.parseColor("#CBCBCB"));
txt_end.setTextColor(Color.parseColor("#7E7E7E"));
txt_end.setText("You ended the .");
img_end.setImageResource(R.drawable.cross_circleclick);
txt_end.setGravity(Gravity.CENTER);
ll_end[groupPosition].setClickable(false);
}
ll_end[groupPosition].setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v("", TAG + "==childposition==" + groupPosition);
if (endornot.get(groupPosition) == 0) {
if (Utils.detectInternetConnection(context)) {
new post_EndorClose().execute(childText.getB_id(), "1", groupPosition + "");
} else {
progressDialog.showWarningDialog_Click(getString(R.string.no_internet), new OnClickListener() {
#Override
public void onClick(View v) {
progressDialog.dialogDismiss();
try {
Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS);
startActivity(callGPSSettingIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
} else {
}
}
});
}
if (childText.getIs_close().equalsIgnoreCase("0")) {
ll_closeaceess[groupPosition].setBackgroundColor(Color.parseColor("#E7E7E7"));
txt_closeacess.setTextColor(Color.parseColor("#7E7E7E"));
txt_closeacess.setText("Access to the closed");
txt_closeacess.setGravity(Gravity.CENTER);
ll_closeaceess[groupPosition].setClickable(false);
} else {
ll_closeaceess[groupPosition].setBackgroundColor(Color.parseColor("#006500"));
txt_closeacess.setTextColor(Color.parseColor("#043303"));
txt_closeacess.setText("Close access to ");
ll_closeaceess[groupPosition].setClickable(true);
txt_closeacess.setGravity(Gravity.RIGHT);
if (aceessdeniedornot.get(groupPosition) == 0) {
} else {
ll_closeaceess[groupPosition].setBackgroundColor(Color.parseColor("#E7E7E7"));
txt_closeacess.setTextColor(Color.parseColor("#7E7E7E"));
txt_closeacess.setText("Access to the closed");
txt_closeacess.setGravity(Gravity.CENTER);
ll_closeaceess[groupPosition].setClickable(false);
}
ll_closeaceess[groupPosition].setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v("", TAG + "==childposition==" + groupPosition);
if (aceessdeniedornot.get(groupPosition) == 0) {
if (Utils.detectInternetConnection(context)) {
new post_EndorClose().execute(childText.getB_id(), "2", groupPosition + "");
} else {
progressDialog.showWarningDialog_Click(getString(R.string.no_internet), new OnClickListener() {
#Override
public void onClick(View v) {
progressDialog.dialogDismiss();
try {
Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS);
startActivity(callGPSSettingIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
} else {
}
}
});
}
return convertView;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
Please help me out I'm stucked here still I am trying to work on it but I have time constaint.
Thanks!
I got to say this first, your code is really hard to read.
Try to split using methods the view creation code from your busyness code on getGroupView and getChildView. Also you could use ViewHolder pattern on getChildView to hold your views instead of thoses arrays (ll_whoaccpted, etc...)
TextUtils.isEmpty() can help you check better is your String are empty or null
if (TextUtils.isEmpty(headerTitle.getRemaining_completion_time()))
//instead of
if (headerTitle.getRemaining_completion_time().equalsIgnoreCase("") || headerTitle.getRemaining_completion_time() == null)
Make Sent_ListAdapter implement OnClickListener instead of recreating the listener (new) each time Android gets a View for your list. Add a condition on the view parameter to check which view type was click.
Work with Date and SimpleDataFormat on CountDownTimer, thoses manual string formatting are just awfull and unreadable
Well now to the main subject :
on scrolling expandable list view timer restarts
This happends because a ListView recreates the views/groups that are not showned (calling the getView/getGroup methods) to reuse the rows for other data.
If you want to avoid this you should create and start your counters outside the getView and getGroup (the constructor is a good place).
on expand and collapse timer restarts
Exactly the same thing that happends on the first problem.
on event on child button i need to update particular position's text
on parentview
I didn't really get this so am guessing that you want to change the text of a TextView on the main layout (the one containing the listview). Well you need to give a reference of that TextView to the Sent_ListAdapter.
Or, instead of passing a generic Context to the Sent_ListAdapter pass the Activity/Fragment it self :
public Sent_ListAdapter(MyActivity activty, List<SentModel> listDataHeader, HashMap<SentModel, List<SentModel>> listChildData) {
this._myactivity = myactivity;
this._listDataHeader = listDataHeader;
...
}
// The listener that handles all the events of your Sent_ListAdapter
#Override
public void onClick(View v) {
if(v.getTag() == "theBoutonThatShouldResetTheCounter") { //or other condition
myactivite.myTextView.setText("------");
}
}
Edit
But how will I get position in constructor for every row?
You need to think the other way around : the listview uses your datasource to show the rows. So you need to loop over the elements on your datasource (listDataHeader in your case). Something like :
private List<CountDownTimer> counters;
public Sent_ListAdapter(Context context, List<SentModel> listDataHeader, HashMap<SentModel, List<SentModel>> listChildData) {
...
counters = new ArrayList()<>;
for(SentModel model : listDataHeader) {
long milliseco = model.getRemainingTimeInMs(); //TODO: create something like this or figure out how to get your couters starting times on ms
CountDownTimer cdt = new MyCountDownTimer(milliseco, 1000);
cdt.start(); // I don't know when you want to start your counters, if they start at the same time it could be here
}
}
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
...
datetime_element = (TextView) convertView.findViewById(R.id.datetime_element);
deadline = (TextView) convertView.findViewById(R.id.deadline);
...
CountDownTimer cdt = counters.get(groupPosition);
cdt.setTv1 = datetime_element;
cdt.setTv2 = deadline;
...
}
public class MyCountDownTimer extends CountDownTimer {
public TextView tv1; //TODO: make setters instead of public
public TextView tv2; //TODO: make setters instead of public
public MyCountDownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
//Only use this if u have something to do each tick
SimpleDateFormat df = new SimpleDateFormat(" dd,hh:mm:ss");
Date timeRemaining = //TODO: figure out how you calculate your remaining time
if(tv1 != null) {
tv1.setText(df.format(timeRemaining));
}
}
#Override
public void onFinish() {
if(tv1 != null && tv2!= null) {
tv1.setText("Completion time over");
tv2.setVisibility(View.GONE);
}
}
}

Refresh ListView pressing option DialogFragment

I have a listview that clicking on an element shows a DialogFragmen with several options, options that take the user will be shown in the item of listview TextView and I get the following error in execution:
Activity app.gepv.Inventario has leaked IntentReceiver com.immersion.android.haptics.HapticFeedbackManager$HapticFeedbackBroadcastReceiver#426e94b8 that was originally registered here. Are you missing a call to unregisterReceiver()?
Enter the code that I think is important, if you need anything else edit the question :)
This is mi DialogFragment:
final String[] items= equiDisp.toArray(new String[equiDisp.size()]);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Asigne equipo/equipos:")
.setOnKeyListener(new Dialog.OnKeyListener(){
public boolean onKey(DialogInterface arg0, int keyCode,KeyEvent event) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK)
{
finish();
//dialog.dismiss();
actualizarDisplay();
}
return true;
}
})
.setMultiChoiceItems(items, null, new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int item, boolean isChecked) {
Log.i("Dialogos", "Opción elegida: " + items[item]);
if(isChecked)
{
marcado.add(items[item]);
Log.i("Dialogos", "Marcado: " + items[item]);
obras.get(pulsado).equiA.add(Integer.parseInt(items[item]));
for( int k=0; k< obras.get(pulsado).equiA.size(); k++)
{
Log.i("Dialogos", "Equipos: " + obras.get(pulsado).equiA.get(k) );
}
}
}
});
So far everything is running well because I check with Log.i
This is the function ActualizarDisplay():
public void actualizarDisplay()
{
adapter = new ObrasAdapter(this, obras);
lvObras = (ListView) findViewById(R.id.lvItems);
lvObras.setAdapter(adapter);
lvObras.setOnItemClickListener(this);
}
And this is my custom dataApdapter for the listview:
public class ObrasAdapter extends ArrayAdapter<Obra> {
private Context context;
private ArrayList<Obra> datos;
public ObrasAdapter(Context context, ArrayList<Obra> datos) {
super(context, R.layout.listview_item, datos);
this.context = context;
this.datos = datos;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View item = convertView;
ObrasHolder holder;
if (item == null) {
item = LayoutInflater.from(context).inflate(R.layout.listview_item,
null);
holder = new ObrasHolder();
holder.foto = (ImageView) item.findViewById(R.id.imgAnimal);
holder.num = (TextView) item.findViewById(R.id.numC);
holder.iden = (TextView) item.findViewById(R.id.idenC);
holder.ubi = (TextView) item.findViewById(R.id.ubiC);
holder.hombres = (TextView) item.findViewById(R.id.homC);
holder.material = (TextView) item.findViewById(R.id.matC);
holder.eq1 = (TextView) item.findViewById(R.id.eq1);
holder.eq2 = (TextView) item.findViewById(R.id.eq2);
holder.eq3 = (TextView) item.findViewById(R.id.eq3);
holder.eq4 = (TextView) item.findViewById(R.id.eq4);
holder.fondo = (RelativeLayout) item.findViewById(R.id.fondobra);
item.setTag(holder);
}
holder = (ObrasHolder) item.getTag();
holder.foto.setImageResource(datos.get(position).getDrawableImageID());
if(datos.get(position).getPrioridad()==1)
{
holder.num.setTextColor(Color.RED);
holder.iden.setTextColor(Color.RED);
holder.ubi.setTextColor(Color.RED);
holder.hombres.setTextColor(Color.RED);
holder.material.setTextColor(Color.RED);
holder.eq1.setTextColor(Color.RED);
holder.eq2.setTextColor(Color.RED);
holder.eq3.setTextColor(Color.RED);
holder.eq4.setTextColor(Color.RED);
}
if(datos.get(position).getPrioridad()==2)
{
holder.num.setTextColor(Color.parseColor("#FF8000"));
holder.iden.setTextColor(Color.parseColor("#FF8000"));
holder.ubi.setTextColor(Color.parseColor("#FF8000"));
holder.hombres.setTextColor(Color.parseColor("#FF8000"));
holder.material.setTextColor(Color.parseColor("#FF8000"));
holder.eq1.setTextColor(Color.parseColor("#FF8000"));
holder.eq2.setTextColor(Color.parseColor("#FF8000"));
holder.eq3.setTextColor(Color.parseColor("#FF8000"));
holder.eq4.setTextColor(Color.parseColor("#FF8000"));
}
if(datos.get(position).getPrioridad()==3)
{
holder.num.setTextColor(Color.GREEN);
holder.iden.setTextColor(Color.GREEN);
holder.ubi.setTextColor(Color.GREEN);
holder.hombres.setTextColor(Color.GREEN);
holder.material.setTextColor(Color.GREEN);
holder.eq1.setTextColor(Color.GREEN);
holder.eq2.setTextColor(Color.GREEN);
holder.eq3.setTextColor(Color.GREEN);
holder.eq4.setTextColor(Color.GREEN);
}
holder.num.setText(datos.get(position).getNum());
holder.iden.setText(datos.get(position).getIden());
holder.ubi.setText(datos.get(position).getUb());
holder.hombres.setText(datos.get(position).getHom());
holder.material.setText(datos.get(position).getMat());
if(datos.get(position).getEstado()==1)
{
holder.fondo.setBackgroundColor(Color.GREEN);
holder.num.setTextColor(Color.WHITE);
holder.iden.setTextColor(Color.WHITE);
holder.ubi.setTextColor(Color.WHITE);
holder.hombres.setTextColor(Color.WHITE);
holder.material.setTextColor(Color.WHITE);
holder.eq1.setTextColor(Color.WHITE);
holder.eq1.setTextColor(Color.WHITE);
holder.eq1.setTextColor(Color.WHITE);
holder.eq1.setTextColor(Color.WHITE);
}
if(! datos.get(position).equiA.isEmpty())
{
for(int i=0; i<datos.get(position).equiA.size();i++)
{
if(i == 0)
{
holder.eq1.setText(String.valueOf(datos.get(position).equiA.get(i)));
}
if(i == 1)
holder.eq2.setText(String.valueOf(datos.get(position).equiA.get(i)));
if(i == 2)
holder.eq3.setText(String.valueOf(datos.get(position).equiA.get(i)));
if(i == 3)
holder.eq4.setText(String.valueOf(datos.get(position).equiA.get(i)));
}
}
else
{
holder.eq1.setVisibility(View.INVISIBLE);
holder.eq2.setVisibility(View.INVISIBLE);
holder.eq3.setVisibility(View.INVISIBLE);
holder.eq4.setVisibility(View.INVISIBLE);
}
return item;
}
}
Can anyone help me?
I think i must to do something as:
#Override
protected void onStop()
{
unregisterReceiver(sendBroadcastReceiver);
unregisterReceiver(deliveryBroadcastReceiver);
super.onStop();
}

Buttons displaying download progress (from background thread) get mixed up when scrolling in Android

I have a bug that I think is due to the way that lists reuse objects. I have a list of download buttons that get a progress readout when downloading. The update code is in a background thread.
When I scroll the list, the buttons that are showing progress jump into other list elements. How can I stop this? It's difficult to visualize, so I made a video of it:
http://www.youtube.com/watch?v=EiT2YWb2Prs&feature=youtu.be
BTW, the video was made by my client, so disregard the "samsung bug" bit. I'm the developer...
Here is the code:
public class VideosActivity extends Activity {
ListView video_list;
CustomList2 adapter;
File storage_dir;
String s3_bucket = "xx";
String s3_dir = "android/vol1/"; //the directory after the boucket that the files are stored in (do not add first slash)
Handler handler = new Handler(); //'tunnel' through whci other threads communicate with main thread
ArrayList<String> arr_videos = new ArrayList<String>();
ArrayList<String> arr_sdcardvideos = new ArrayList<String>();
int images[] = {R.drawable.kr115,R.drawable.kr200,R.drawable.kr201,R.drawable.kr202,R.drawable.kr203,R.drawable.kr205,R.drawable.kr206,R.drawable.kr207,R.drawable.kr208,R.drawable.kr209,R.drawable.kr210,R.drawable.kr211,R.drawable.kr212,R.drawable.kr213,R.drawable.kr213,R.drawable.kr214,R.drawable.kr215,R.drawable.kr216,R.drawable.kr210,R.drawable.kr211,R.drawable.kr212,R.drawable.kr213};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
storage_dir = getApplicationContext().getExternalFilesDir(null); //private to app, removed with uninstall
adapter = new CustomList2(this, R.layout.customlist, arr_videos);
video_list = (ListView)findViewById(R.id.list);
video_list.setAdapter(adapter); //set adapter that specifies list contents
ensureStorageDirExists( storage_dir ); //make sure storage dir exists
set_sdcard_video_data(); //store vids arleady on card
set_video_data(); //store vid dat in array
if(!have_connection())
{
Toast.makeText(this, "No Internet connection", Toast.LENGTH_LONG).show();
return;
}
}
protected void ensureStorageDirExists( File dir )
{
if (!dir.exists())
{
dir.mkdirs();
}
}
public void set_sdcard_video_data()
{
arr_sdcardvideos.clear();
for(File f:storage_dir.listFiles())
{
arr_sdcardvideos.add( f.getName() );
}
}
public void set_video_data()
{
arr_videos.add("02Posture_and_Walk.m4v");
arr_videos.add("03Embrace_Connection_and_Musicality.m4v");
arr_videos.add("04Left_Turning_Check_Step.m4v");
arr_videos.add("05Basic_Right_Turn.m4v");
arr_videos.add("06Ocho_Cortado.m4v");
arr_videos.add("07Media_Vuelta.m4v");
arr_videos.add("08The_Cross.m4v");
arr_videos.add("09Front_Ochos.m4v");
arr_videos.add("10The_Cross_in_Cross_System.m4v");
arr_videos.add("11Back_Ochos.m4v");
arr_videos.add("12Molinete_Giro.m4v");
arr_videos.add("13Right_Turn.m4v");
arr_videos.add("14Combining_All_the_Elements_1.m4v");
arr_videos.add("15Combining_All_the_Elements_2.m4v");
arr_videos.add("16Combining_All_the_Elements_3.m4v");
arr_videos.add("17Combining_All_the_Elements_4.m4v");
arr_videos.add("18Combining_All_the_Elements_5.m4v");
arr_videos.add("19Combining_All_the_Elements_6.m4v");
arr_videos.add("20Demo_Using_All_the_Elements.m4v");
arr_videos.add("36Etiquette.m4v");
}
public SharedPreferences stored_vals()
{
return PreferenceManager.getDefaultSharedPreferences(this);
}
public boolean have_connection()
{
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if(cm.getActiveNetworkInfo()!=null && cm.getActiveNetworkInfo().isConnected() && cm.getActiveNetworkInfo().isAvailable())
{
return true;
}
else
{
return false;
}
}
public void download_video(int position, View btn)
{
}
public class CustomList2 extends ArrayAdapter<String>
{
View view;
int position;
Button btn;
public CustomList2(Context context, int layout_id, ArrayList<String> objects)
{
super(context, layout_id, objects);
}
#Override
public View getView(final int position, View convertView, ViewGroup view_group)
{
set_view(convertView);
this.position = position;
TextView text_view = (TextView) view.findViewById(R.id.name);
ImageView image = (ImageView) view.findViewById(R.id.img);
btn = (Button) view.findViewById(R.id.play);
prepare_btn();
text_view.setText( list_text() );
image.setImageResource(images[position]);
return view;
}
public String list_text()
{
String s = arr_videos.get( position ).replace("_", " ").replace(".m4v", "");
s = s.substring(2, s.length());
return s;
}
public void set_view(View convertView)
{
if(convertView == null)
{
LayoutInflater inflater = getLayoutInflater();
view = inflater.inflate(R.layout.customlist, null);
}
else
{
view = convertView;
}
}
public Boolean is_downloaded()
{
return arr_sdcardvideos.contains(arr_videos.get(position));
}
public void prepare_btn()
{
btn.setTag((Integer) position);
if(is_downloaded() == true)
{
btn.setText("Play ");
btn.setEnabled(true);
btn.setOnClickListener( new OnClickListener()
{
public void onClick(View btn)
{
int position = (Integer) btn.getTag();
Intent i = new Intent(VideosActivity.this, PlayVideoActivity.class);
String video_path = storage_dir + "/" + arr_videos.get(position);
Log.v("video_path", video_path);
i.putExtra("video_path", video_path);
startActivity(i);
}
});
}
else
{
btn.setText("Download ");
btn.setOnClickListener( new OnClickListener()
{
public void onClick(View btn)
{
int position = (Integer) btn.getTag();
btn.setEnabled(false);
//download_video( position, btn );
Download d = new Download();
d.start(position, (Button) btn);
}
});
}
}
}
public class Download
{
File new_video_file;
Button btn; //the progress meter needs to know what button called this. set via setter method below.
int position;
com.amazonaws.services.s3.transfer.Download download;
protected void start(int position, Button btn)
{
this.btn = (Button) btn;
this.position = position;
this.new_video_file = new File(storage_dir, arr_videos.get(position)); //local file to be writtent to
AWSCredentials credentials = new BasicAWSCredentials("xx", "xx" );
TransferManager tx = new TransferManager(credentials);
this.download = tx.download(s3_bucket, s3_dir + arr_videos.get(position), new_video_file);
download.addProgressListener(new ProgressListener()
{
public void progressChanged(final ProgressEvent pe)
{
handler.post( new Runnable()
{
#Override
public void run()
{
if ( pe.getEventCode() == ProgressEvent.COMPLETED_EVENT_CODE )
{
Download.this.onComplete();
}
else
{
Download.this.onProgressUpdate();
}
}
});
}
});
}
//protected void onProgressUpdate(Double progress)
protected void onProgressUpdate()
{
Double progress = this.download.getProgress().getPercentTransfered();
String percent = progress.intValue() + "%";
Log.v("runnable", percent);
btn.setText(percent);
Log.v("dev", progress + "");
}
protected void onComplete()
{
Log.v("dev", "download complete!!!");
set_sdcard_video_data();
adapter.notifyDataSetChanged();
// this.download.abort();
}
}
}
Your Download Thread keeps a reference to the Button. The Buttons get reused though for different list elements when you scroll. You need to find a way to update the Button in the Thread somehow. The Button in the Thread can also be null, when the list element is not visible.
Edit:
It's really not that complicated. First of all: you should use a ViewHolder, that's gonna make your life much easier. Then you could do something like that
#Override
public View getView(final int position, View convertView, ViewGroup view_group) {
View view = null;
ViewHolder holder = null;
if(convertView == null){
view = {inflate view}
view.setTag(holder = new ViewHolder());
holder.view1 = view.findViewById(...);
{get rest of the views}
}else{
view = convertView;
holder = (ViewHolder)view.getTag();
}
if(holder.getDownloadThread() != null){
holder.getDownloadThread().setButton(null);
}
...
}
You get the idea.

Categories

Resources