I'm having trouble making a listview item clickable. I've tried if statments, onclicklisteners and I'm still not having any success, does anyone know how to do this? I also have another class to get the strings, but I don't think it is needed. If you could help me out with this, I would appreciate it! Thanks!Here is my code:
import java.util.ArrayList;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends ListActivity{
private ProgressDialog m_ProgressDialog = null;
private ArrayList<Order> m_orders = null;
private OrderAdapter m_adapter;
private Runnable viewOrders;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m_orders = new ArrayList<Order>();
this.m_adapter = new OrderAdapter(this, R.layout.row, m_orders);
setListAdapter(this.m_adapter);
viewOrders = new Runnable(){
#Override
public void run() {
getOrders();
}
};
Thread thread = new Thread(null, viewOrders, "MagentoBackground");
thread.start();
m_ProgressDialog = ProgressDialog.show(MainActivity.this,
"Please wait...", "Retrieving data ...", true);
}
private Runnable returnRes = new Runnable() {
#Override
public void run() {
if(m_orders != null && m_orders.size() > 0){
m_adapter.notifyDataSetChanged();
for(int i=0;i<m_orders.size();i++)
m_adapter.add(m_orders.get(i));
}
m_ProgressDialog.dismiss();
m_adapter.notifyDataSetChanged();
}
};
private void getOrders(){
try{
m_orders = new ArrayList<Order>();
Order o1 = new Order();
o1.setOrderName("Item 1");
o1.setOrderStatus("2012");
o1.setorderpic(R.drawable.bulb);
Order o2 = new Order();
o2.setOrderName("Item 2");
o2.setOrderStatus("Completed");
o2.setorderpic(R.drawable.bulb);
m_orders.add(o1);
m_orders.add(o2);
Thread.sleep(5000);
Log.i("ARRAY", ""+ m_orders.size());
} catch (Exception e) {
Log.e("BACKGROUND_PROC", e.getMessage());
}
runOnUiThread(returnRes);
}
private class OrderAdapter extends ArrayAdapter<Order> {
private ArrayList<Order> items;
public OrderAdapter(Context context, int textViewResourceId, ArrayList<Order> items) {
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
Order o = items.get(position);
if (o != null) {
TextView tt = (TextView) v.findViewById(R.id.toptext);
TextView bt = (TextView) v.findViewById(R.id.bottomtext);
ImageView ct = (ImageView) v.findViewById(R.id.icon);
if (tt != null) {
tt.setText("Name: "+o.getOrderName()); }
if(bt != null){
bt.setText("Status: "+ o.getOrderStatus());
}
if(ct !=null){
ct.setImageResource(o.getorderpic());
}
}
return v;
}
}
You can use view's OnClickListener in getView() of your custom adapter
v.setOnClickListener(new OnClickListener()
{
public void onClick(View v) {
// do something on click
}
});
http://developer.android.com/reference/android/view/View.OnClickListener.html
You should override ListActivity's onListItemClick method. This is what ListActivity is made for.
onListItemClick()
Related
I have a android studio project and use 'com.timehop.stickyheadersrecyclerview:library:0.4.3#aar'
library it works fine but when I create a new project using same code It show me the following error in line 26 StickyRecyclerHeadersAdapter<CustomAdapter.MyHeadingViewHolder> { of CustomAdapter class:
Type parameter 'com.vatexpress.service.CustomAdapter.MyHeadingViewHolder' is not within its bound; should extend 'android.support.v7.widget.RecyclerView.ViewHolder'
and also show me following error in line 75 recyclerView.addItemDecoration(new StickyRecyclerHeadersDecoration(customAdapter));of ManinActivity class:
Type parameter 'com.vatexpress.service.CustomAdapter.MyHeadingViewHolder' is not within its bound; should extend 'android.support.v7.widget.RecyclerView.ViewHolder'
Here is my CustomAdapter class:
package com.vatexpress.service;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter;
import java.util.ArrayList;
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyChildViewHolder>
implements Filterable,
StickyRecyclerHeadersAdapter<CustomAdapter.MyHeadingViewHolder> {
private Context context;
private Activity activity;
private ArrayList<Model> dataholder;
ArrayList<Model> backup;
MyDatabaseHelper obj = null;
String code, nature, name, sd, vat, vds, vat_ref, vds_ref, about;
public static final int CHILD_LIST = 1;
public static final int HEADER = 2;
CustomAdapter(Activity activity, Context context, ArrayList<Model> dataholder){
this.activity = activity;
this.context = context;
this.dataholder = dataholder;
backup=new ArrayList<>(dataholder);
}
#NonNull
#Override
public MyChildViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.my_row, parent, false);
return new MyChildViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final MyChildViewHolder holder, final int position) {
// if (holder instanceof MyChildViewHolder) {
final Model temp=dataholder.get(position);
holder.service_code.setText(dataholder.get(position).getService_code());
holder.service_name.setText(dataholder.get(position).getService_name());
//Recyclerview onClickListener
holder.mainLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, DetailActivity.class);
obj = new MyDatabaseHelper(context);
Cursor cursor = obj.getData(temp.id);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
code = cursor.getString(0);
nature = cursor.getString(2);
name = cursor.getString(1);
sd = cursor.getString(3);
vat = cursor.getString(4);
vds = cursor.getString(5);
vat_ref = cursor.getString(6);
vds_ref = cursor.getString(7);
about = cursor.getString(8);
} while (cursor.moveToNext());
}
}
intent.putExtra("code", code);
intent.putExtra("nature", nature);
intent.putExtra("servicename", name);
intent.putExtra("sd", sd);
intent.putExtra("vat", vat);
intent.putExtra("vds", vds);
intent.putExtra("vat_ref", vat_ref);
intent.putExtra("vds_ref", vds_ref);
intent.putExtra("about", about);
activity.startActivityForResult(intent, 1);
}
});
// }
// else if(holder instanceof MyHeadingViewHolder) {
// MyHeadingViewHolder myHeadingViewHolder = (MyHeadingViewHolder) holder;
// myHeadingViewHolder.heading.setText(dataholder.get(position).service_heading);
// }
}
#Override
public long getHeaderId(int position) {
return dataholder.get(position).getSection();
}
#Override
public MyHeadingViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.heading_layout, parent, false);
return new MyHeadingViewHolder(view);
}
#Override
public void onBindHeaderViewHolder(MyHeadingViewHolder myHeadingViewHolder, int i) {
myHeadingViewHolder.heading.setText(dataholder.get(i).getService_heading());
}
#Override
public int getItemCount() {
return dataholder.size();
}
#Override
public Filter getFilter() {
return filter;
}
Filter filter=new Filter() {
#Override
// background thread
protected FilterResults performFiltering(CharSequence keyword)
{
ArrayList<Model> filtereddata=new ArrayList<>();
if(keyword.toString().isEmpty())
filtereddata.addAll(backup);
else
{
for(Model obj : backup)
{
if(obj.getService_name().toString().toLowerCase().contains(keyword.toString().toLowerCase()))
filtereddata.add(obj);
}
}
FilterResults results=new FilterResults();
results.values=filtereddata;
return results;
}
#Override // main UI thread
protected void publishResults(CharSequence constraint, FilterResults results)
{
dataholder.clear();
dataholder.addAll((ArrayList<Model>)results.values);
notifyDataSetChanged();
}
};
// #Override
// public int getItemViewType(int position) {
// if (dataholder.get(position).typeHeading)
// {
// return HEADER;
// }
// else {
// return CHILD_LIST;
// }
// }
class MyChildViewHolder extends RecyclerView.ViewHolder {
TextView service_code, service_name;
LinearLayout mainLayout;
MyChildViewHolder(#NonNull View itemView) {
super(itemView);
service_code = itemView.findViewById(R.id.service_code);
service_name = itemView.findViewById(R.id.service_name);
mainLayout = itemView.findViewById(R.id.mainLayout);
//Animate Recyclerview
Animation translate_anim = AnimationUtils.loadAnimation(context, R.anim.translate_anim);
mainLayout.setAnimation(translate_anim);
}
}
class MyHeadingViewHolder extends RecyclerView.ViewHolder {
TextView heading;
public MyHeadingViewHolder(#NonNull View itemView) {
super(itemView);
heading = itemView.findViewById(R.id.heading_name);
}
}
}
Here is my MainActivity class:
package com.vatexpress.service;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.SearchView;
import android.widget.TextView;
import android.widget.Toast;
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
public final class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE_SPEECH_INPUT =1000 ;
RecyclerView recyclerView;
TextView noSearchResultsFoundText;
EditText editText;
ImageView clearQueryImageView ;
ImageView voiceSearchImageView;
MyDatabaseHelper myDB;
ArrayList<Model> dataholder;
CustomAdapter customAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.search_list);
noSearchResultsFoundText = findViewById(R.id.no_search_results_found_text);
myDB = new MyDatabaseHelper(MainActivity.this);
try {
myDB.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDB.openDataBase();
} catch (SQLException sqle) {
throw sqle;
}
storeDataInArrays();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
customAdapter = new CustomAdapter(MainActivity.this,this, dataholder);
recyclerView.setAdapter(customAdapter);
recyclerView.addItemDecoration(new StickyRecyclerHeadersDecoration(customAdapter));
editText = (EditText) findViewById(R.id.search_edit_text);
editText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {
customAdapter.getFilter().filter(s.toString());
if (editText.getText().toString().isEmpty()){
clearQueryImageView.setVisibility(View.GONE);
voiceSearchImageView.setVisibility(View.VISIBLE);
}else{
clearQueryImageView.setVisibility(View.VISIBLE);
voiceSearchImageView.setVisibility(View.GONE);
}
}
});
voiceSearchImageView = findViewById(R.id.voice_search_query);
//button clic to show speech to text dilog
voiceSearchImageView.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
speak();
}
} );
clearQueryImageView = findViewById(R.id.clear_search_query);
clearQueryImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
editText.setText("");
}
});
}
private void speak() {
//intent is show speech to text dialog
Intent intent= new Intent( RecognizerIntent.ACTION_RECOGNIZE_SPEECH );
intent.putExtra( RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra( RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault() );
intent.putExtra( RecognizerIntent.EXTRA_PROMPT, "HI speak something" );
// Start intent
try {
//in there was no errror
//show dilog
startActivityForResult( intent, REQUEST_CODE_SPEECH_INPUT);
}
catch(Exception e){
//show messageof error and show
Toast.makeText( this,""+e.getMessage(), Toast.LENGTH_SHORT ).show();
}
}
//recive voice input and handle it
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult( requestCode, resultCode, data );
switch (requestCode){
case REQUEST_CODE_SPEECH_INPUT:{
if(resultCode==RESULT_OK && null!=data){
//get text arry form voice intent
ArrayList<String> result=data.getStringArrayListExtra( RecognizerIntent.EXTRA_RESULTS );
//set to text view
editText.setText( result.get( 0 ) );
}
break;
}
}
}
public void storeDataInArrays(){
dataholder = new ArrayList<>();
String code = "";
boolean firstTime = true;
int section = 0, count = 0;
Cursor cursor = myDB.readAllData();
if(cursor.getCount() == 0){
noSearchResultsFoundText.setVisibility(View.VISIBLE);
}else{
while (cursor.moveToNext()){
if (firstTime) {
code = cursor.getString(1);
Model obj=new Model(cursor.getString(0),cursor.getString(1), cursor.getString(2), cursor.getString(3), true, section);
firstTime = false;
dataholder.add(obj);
}
else
{
if (!code.equals(cursor.getString(1))) {
section = count;
Model obj=new Model(cursor.getString(0),cursor.getString(1), cursor.getString(2), cursor.getString(3), true, section);
dataholder.add(obj);
code = cursor.getString(1);
}
else
{
Model obj=new Model(cursor.getString(0),cursor.getString(1), cursor.getString(2), cursor.getString(3), false, section);
dataholder.add(obj);
}
}
count++;
}
noSearchResultsFoundText.setVisibility(View.GONE);
}
}
}
Please gives me solution how can I solve this!
If I click the button CHECKOUT a pop up shows up. In this pop up, you have the chance to abort the transaction. So if you abort the transaction all the values for the Items (French fires, Water, Burger) should be 0 again as seen in the picture below. Right now when i abort the transaction the values stay the way i configured them before. Can you help me with that?
OrderActivity.java
package com.nfc.netvision;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.Dialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.firebase.auth.FirebaseAuth;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Locale;
import static android.widget.Toast.*;
public class OrderActivity extends AppCompatActivity implements OrderAdapter.TotalListener {
RecyclerView recyclerView;
ArrayList<ModelOrder> orderArrayList;
TextView textView_order_price;
TextView textView_order_count;
Dialog epicDialog;
Button btnCheckout;
Button btnAbort;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
recyclerView = findViewById(R.id.recyclerview_order_scroll);
textView_order_price = findViewById(R.id.textView_order_price);
textView_order_count = findViewById(R.id.textView_order_count);
btnCheckout = (Button) findViewById(R.id.btnCheckout);
orderArrayList = new ArrayList<>();
orderArrayList.add(new ModelOrder(R.drawable.coke, "Coka Cola", "Eine Cola hält dich wach und schmeckt dazu.", "3",0));
orderArrayList.add(new ModelOrder(R.drawable.fastfood, "Pommes", "Fritten für die Titten.", "5",0));
orderArrayList.add(new ModelOrder(R.drawable.water, "Wasser", "Still und sanft, so mag ich es.", "5",0));
orderArrayList.add(new ModelOrder(R.drawable.burger, "Burger", "Ach mir fällt nichts ein.", "10",0));
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
RecyclerView.LayoutManager recLiLayoutManager = layoutManager;
recyclerView.setLayoutManager(recLiLayoutManager);
OrderAdapter adapter = new OrderAdapter(this, orderArrayList, this);
recyclerView.setAdapter(adapter);
epicDialog = new Dialog(this);
btnCheckout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showWaitingPopUp();
}
});
}
private void showWaitingPopUp() {
epicDialog.setContentView(R.layout.order_popup_waiting);
epicDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
btnAbort = (Button) epicDialog.findViewById(R.id.btnAbort);
btnAbort.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
epicDialog.dismiss();
}
});
epicDialog.show();
}
#Override
public void onTotalChanged(String result) {
NumberFormat n = NumberFormat.getCurrencyInstance(Locale.GERMANY);
textView_order_price.setText( n.format(Integer.parseInt(result)));
}
#Override
public void onCountChanged(String result) {
textView_order_count.setText(result);
}
}
OrderAdapter.java
package com.nfc.netvision;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.w3c.dom.Text;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Locale;
public class OrderAdapter extends RecyclerView.Adapter<OrderAdapter.ViewHolder> {
private int totalAmount;
private int totalItems;
private Context mContext;
private ArrayList<ModelOrder> nList;
private TotalListener listener;
interface TotalListener{
void onTotalChanged(String result);
void onCountChanged(String result);
}
OrderAdapter(Context context, ArrayList<ModelOrder> list, TotalListener listener) {
mContext = context;
nList = list;
this.listener = listener;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View view = layoutInflater.inflate(R.layout.recyclerview_order_items, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
final ModelOrder orderItem = nList.get(position);
ImageView image = holder.item_image;
final TextView name, place, price;
name = holder.item_name;
place = holder.item_place;
price = holder.item_price;
image.setImageResource(orderItem.getImage());
name.setText(orderItem.getName());
place.setText(orderItem.getPlace());
price.setText(orderItem.getPrice());
holder.order_item_minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(orderItem.getCounter() > 0) {
orderItem.setCounter(orderItem.getCounter()-1);
holder.order_item_count.setText("" + orderItem.getCounter());
calculatePrice(Integer.parseInt((String) price.getText()), false);
countItems(orderItem.getCounter(), false);
}
}
});
holder.order_item_plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(orderItem.getCounter() < 9) {
orderItem.setCounter(orderItem.getCounter() + 1);
holder.order_item_count.setText("" + orderItem.getCounter());
calculatePrice(Integer.parseInt((String) price.getText()), true);
countItems(orderItem.getCounter(), true);
}
}
});
}
#Override
public int getItemCount() {
return nList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView item_image;
TextView item_name, item_place, item_price,order_item_minus,order_item_count, order_item_plus;
public ViewHolder(#NonNull View itemView) {
super(itemView);
item_image = itemView.findViewById(R.id.order_item_image);
item_name = itemView.findViewById(R.id.order_item_name);
item_place = itemView.findViewById(R.id.order_item_place);
item_price = itemView.findViewById(R.id.order_item_price);
order_item_minus = itemView.findViewById(R.id.order_item_minus);
order_item_plus = itemView.findViewById(R.id.order_item_plus);
order_item_count = itemView.findViewById(R.id.order_item_count);
}
}
private void calculatePrice(int pPrice, boolean pUpDown) {
if(pUpDown) {
totalAmount = totalAmount + pPrice;
}
else {
totalAmount = totalAmount - pPrice;
}
listener.onTotalChanged(totalAmount+ "");
}
private void countItems(int pCounter, boolean pUpDown){
if (pUpDown){
totalItems = totalItems + 1;
}
else{
totalItems = totalItems - 1;
}
listener.onCountChanged(totalItems+ "");
}
}
They stay the way there were because inside your abort button's onClick you just dismiss the dialog and do not change the list values.
I suggest iterating through the list and setting all counters to 0.
Also, don't forget to notify your RecyclerView that you modified something, in this case you reset all counters to 0. Otherwise, you won't see the changes in your app.
private void showWaitingPopUp() {
epicDialog.setContentView(R.layout.order_popup_waiting);
epicDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
btnAbort = epicDialog.findViewById(R.id.btnAbort);
btnAbort.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Set all orders count to 0
for (ModelOrder modelOrder: orderArrayList) {
modelOrder.setCounter(0);
}
// Notify RecyclerView about the changes
adapter.notifyDataSetChanged();
epicDialog.dismiss();
}
});
epicDialog.show();
}
I noticed you didn't have the adapter as a global variable so declare it as such:
public class OrderActivity extends AppCompatActivity implements OrderAdapter.TotalListener {
// other variables
// Change adapter variable to global
OrderAdapter adapter;
// ...
Side notes: I also noticed that you passed your activity twice inside your OrderAdapter constructor.
OrderAdapter adapter = new OrderAdapter(this, orderArrayList, this);
You can simply just do:
OrderAdapter adapter = new OrderAdapter(this, orderArrayList);
Then inside your constructor:
OrderAdapter(Context context, ArrayList<ModelOrder> list) {
mContext = context;
nList = list;
// You can simply cast the context to the listener
listener = (TotalListener) context;
}
Hope my answer helps, happy coding!
Edit: I moved my answers to OP's other questions in the chat.
I am new to android development, and i'm trying to build a simple hymn book,
I'm using bottom navigation, i use fragments on each tab to display numbers and titles of each hymn.
In my favourite fragments i have a list of favourite songs displayed using recycler view fetch from the database.
I use on long click listener to delete songs from the favorite table in the database, but any time i delete a
song my favorite fragment doesn't get refreshed or undated with current items. Please, how can I refresh or update
my favourite fragment anytime i delete a song. thank you!
'''Favourite Adapter''
import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import static android.content.Context.MODE_PRIVATE;
public class FavouriteAdapter extends RecyclerView.Adapter<FavouriteAdapter.ViewHolder> {
private Context favContext;
private ArrayList<String> favNumbers = new ArrayList<>();
private ArrayList<String> favTitles = new ArrayList<>();
public FavouriteAdapter(Context favContext, ArrayList<String> favNumbers, ArrayList<String> favTitles) {
this.favContext = favContext;
this.favNumbers = favNumbers;
this.favTitles = favTitles;
}
#Override
public FavouriteAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.favourite_list_items, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(final FavouriteAdapter.ViewHolder holder, final int position) {
holder.textViewFavNum.setText(favNumbers.get(position));
holder.textViewFavTitle.setText(favTitles.get(position));
final String hymn_no = favNumbers.get(position);
holder.itemView.setTag(favNumbers.get(position));
holder.favParentLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i;
i = new Intent(view.getContext(), Songs.class);
i.putExtra("numId", favNumbers.get(position));
i.putExtra("titleName", favTitles.get(position));
favContext.startActivity(i);
}
});
holder.favParentLayout.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(final View view) {
new AlertDialog.Builder(view.getContext())
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Are you sure?")
.setMessage("Do you want to delete from favorites?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int which) {
try{
SQLiteDatabase favHymns = favContext.openOrCreateDatabase("Songs", MODE_PRIVATE, null);
favHymns.execSQL("DELETE FROM favorites where hymnNum = '"+hymn_no+"'");
Toast.makeText(favContext.getApplicationContext(), "hymn deleted ", Toast.LENGTH_LONG).show();
}catch(Exception e){
e.printStackTrace();
}
}
})
.setNegativeButton("No", null)
.show();
return true;
}
});
}
#Override
public int getItemCount() {
return favNumbers.size();
}
#Override
public long getItemId(int position){
return position;
}
#Override
public int getItemViewType(int position){
return position;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView textViewFavNum;
public TextView textViewFavTitle;
RelativeLayout favParentLayout;
public ViewHolder(View itemView) {
super(itemView);
textViewFavNum = (TextView) itemView.findViewById(R.id.textViewFavNum);
textViewFavTitle = (TextView) itemView.findViewById(R.id.textViewFavTitle);
favParentLayout = (RelativeLayout) itemView.findViewById(R.id.favParentLayout);
}
}
}
'''favourite fragment'''
import android.app.FragmentManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.logging.Handler;
import static android.content.Context.MODE_PRIVATE;
/**
* A simple {#link Fragment} subclass.
*/
public class Favourites extends Fragment {
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private ArrayList<String> favSongNumbers = new ArrayList<>();
private ArrayList<String> favSongTitles = new ArrayList<>();
private TextView favMessage;
public Favourites() {
// Required empty public constructor
}
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if(view == null) {
view = inflater.inflate(R.layout.fragment_favourites, container, false);
favMessage = (TextView) view.findViewById(R.id.favMessage);
recyclerView = (RecyclerView) view.findViewById(R.id.favRecyclerView);
// adapter.setHasStableIds(true);
Toast.makeText(this.getActivity(), "Long press to delete hymns from favorites", Toast.LENGTH_LONG).show();
initFavSongs();
}
return view;
}
private void initFavSongs(){
try{
favMessage.setText("");
SQLiteDatabase favHymns = this.getActivity().openOrCreateDatabase("Songs", MODE_PRIVATE, null);
Cursor c = favHymns.rawQuery("SELECT hymnNum, hymnTitle FROM favorites", null);
int hymnNumIndex = c.getColumnIndex("hymnNum");
int hymnTitleIndex = c.getColumnIndex("hymnTitle");
if(c.moveToFirst()) {
while (c != null) {
favSongNumbers.add(Integer.toString(c.getInt(hymnNumIndex)) + ". ");
favSongTitles.add(" " + c.getString(hymnTitleIndex));
c.moveToNext();
}
}else{
favMessage.setText("Oops!No favorite songs added yet.");
}
}catch (Exception e){
e.printStackTrace();
}
initRecyclerView();
}
private void initRecyclerView(){
adapter = new FavouriteAdapter(this.getActivity(), favSongNumbers, favSongTitles);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getActivity()));
}
}
Pass a listener to the adapter and invoke it at the time of item delete from database. Then update your list and as well as your adapter.Like this way:
First create a listener:
public interface UpdateListener {
void onValueChangedListener();
}
Initialize the listener in Adapter class that comes from fragment.
private UpdateListener updateListener;
public FavouriteAdapter(Context favContext, ArrayList<String> favNumbers, ArrayList<String> favTitles,UpdateListener updateListener ) {
this.favContext = favContext;
this.favNumbers = favNumbers;
this.favTitles = favTitles;
this.updateListener=updateListener;
}
holder.favParentLayout.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(final View view) {
new AlertDialog.Builder(view.getContext())
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Are you sure?")
.setMessage("Do you want to delete from favorites?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int which) {
try{
SQLiteDatabase favHymns = favContext.openOrCreateDatabase("Songs", MODE_PRIVATE, null);
favHymns.execSQL("DELETE FROM favorites where hymnNum = '"+hymn_no+"'");
Toast.makeText(favContext.getApplicationContext(), "hymn deleted ", Toast.LENGTH_LONG).show();
// when any item delete from database notify the fragment through this
// listener for updating your adapter
updateListener.onValueChangedListener();
}catch(Exception e){
e.printStackTrace();
}
}
})
.setNegativeButton("No", null)
.show();
return true;
}
});
// this method is needed for updating your adapter
public void update(ArrayList<String> favNumbers, ArrayList<String> favTitles){
this.favNumbers = favNumbers;
this.favTitles = favTitles;
}
Implement the listener in your fragment and reinitialize your list.
public class Favourites extends Fragment implements UpdateListener {
private void initRecyclerView(){
// pass listener
adapter = new FavouriteAdapter(this.getActivity(), favSongNumbers, favSongTitles,this);
}
private void updateFavSongs(){
favSongNumbers.clear;
favSongTitles.clear;
try{
favMessage.setText("");
SQLiteDatabase favHymns = this.getActivity().openOrCreateDatabase("Songs", MODE_PRIVATE, null);
Cursor c = favHymns.rawQuery("SELECT hymnNum, hymnTitle FROM favorites", null);
int hymnNumIndex = c.getColumnIndex("hymnNum");
int hymnTitleIndex = c.getColumnIndex("hymnTitle");
if(c.moveToFirst()) {
while (c != null) {
favSongNumbers.add(Integer.toString(c.getInt(hymnNumIndex)) + ". ");
favSongTitles.add(" " + c.getString(hymnTitleIndex));
c.moveToNext();
}
}else{
favMessage.setText("Oops!No favorite songs added yet.");
}
}catch (Exception e){
e.printStackTrace();
}
adapter.update(favSongNumbers,favSongTitles);
adapter.notifyDataSetChanged()
}
#Override
public void onValueChangedListener(){
updateFavSongs();
}
}
I have a custom listview adapter setup up that I need to call in my fragment, but I can't seem the pass my activity to it. I have a very similar set up, but called from within an activity, and it works very well. So, I think the issue is with passing the activity context to the adapter, but I'm not sure how to achieve it.
Below is the code for my fragment, where I make the call to my custom adapter:
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
public class SiblingUnitFragment extends Fragment {
Context siblingContext = this.getActivity();
Activity context = this.getActivity();
ProgressDialog progressDialog;
ListView siblingLVAdapter;
String ReadOnly;
String LexaUser;
String Password;
String SearchValue;
String finalResultSiblings;
String HttpURLSiblings = "https://[myDataSpot]/getSiblings.php";
HashMap<String, String> hashMapSiblings = new HashMap<>();
HttpParse httpParse = new HttpParse();
String[] Uuid;
String[] Usize;
String[] Ustatus;
String SV;
String[] svSeparated;
ListView siblingListView;
public SiblingUnitFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_siblings, container, false);
siblingListView = (ListView) view.findViewById(R.id.SiblingsList);
return view;
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getArguments() != null) {
SV = getArguments().getString("SearchValue");
LexaUser = getArguments().getString("LexaUser");
}
if (SV.contains("-")) {
svSeparated = SV.split("-");
SearchValue = svSeparated[0];
getSiblings(SearchValue, LexaUser);
} else {
SearchValue = SV;
getSiblings(SearchValue, LexaUser);
}
}
public void getSiblings(String searchInput, String lexaUser) {
class SiblingsClass extends AsyncTask<String,Void,String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(siblingContext, "Loading Data", null, true, true);
}
#Override
protected void onPostExecute(String httpResponseMsg) {
super.onPostExecute(httpResponseMsg);
if (httpResponseMsg != null) {
try {
JSONArray json = new JSONArray(httpResponseMsg);
Uuid = new String[json.length()];
Usize = new String[json.length()];
Ustatus = new String[json.length()];
for (int i = 0; i < json.length(); i++) {
JSONObject object = json.getJSONObject(i);
Uuid[i] = object.getString("id");
Usize[i] = object.getString("size");
Ustatus[i] = object.getString("status");
}
siblingLVAdapter = new SiblingsListViewAdapter(context, Uuid, Usize, Ustatus);
siblingListView.setAdapter(siblingLVAdapter);
} catch (JSONException e) {
Log.e("JSONException", "Error: " + e.toString());
Toast.makeText(siblingContext, "Error: " + e.toString(), Toast.LENGTH_LONG).show();
} // catch (JSONException e)
progressDialog.dismiss();
} else {
progressDialog.dismiss();
Toast.makeText(siblingContext, "HttpResponseMsg is null.", Toast.LENGTH_LONG).show();
}
}
#Override
protected String doInBackground(String... params) {
hashMapSiblings.put("searchinput", params[0]);
hashMapSiblings.put("lexauser", params[1]);
finalResultSiblings = httpParse.postRequest(hashMapSiblings, HttpURLSiblings);
return finalResultSiblings;
}
}
SiblingsClass siblingsClass = new SiblingsClass();
siblingsClass.execute(searchInput, lexaUser);
}
}
And this is my code for the adapter:
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class SiblingsListViewAdapter extends BaseAdapter {
Activity context;
String Uuid[];
String Usize[];
String Ustatus[];
public SiblingsListViewAdapter(Activity context, String[] Uuid, String[] Usize, String[] Ustatus) {
super();
this.context = context;
this.Uuid = Uuid;
this.Usize = Usize;
this.Ustatus = Ustatus;
}
public int getCount() {
// TODO Auto-generated method stub
return Uuid.length;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
private class ViewHolder {
TextView txtViewUid;
TextView txtViewSize;
TextView txtViewStatus;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
LayoutInflater inflater = context.getLayoutInflater();
if (convertView == null)
{
convertView = inflater.inflate(R.layout.siblings_list, null);
holder = new ViewHolder();
holder.txtViewUid = (TextView) convertView.findViewById(R.id.SiblingsUid);
holder.txtViewSize = (TextView) convertView.findViewById(R.id.SiblingsSize);
holder.txtViewStatus = (TextView) convertView.findViewById(R.id.SiblingsStatus);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.txtViewUid.setText(Uuid[position]);
holder.txtViewSize.setText(Usize[position]);
holder.txtViewStatus.setText(Ustatus[position]);
return convertView;
}
}
And here is the logcat error:
error: incompatible types: SiblingsListViewAdapter cannot be converted to ListView
All help is appreciated. Thank you!
A per the Fragment Lifecycle, You need to call getContext only after onAttach method of your fragment lifecycle is called otherwise there is no associated activity hence there is no context
so use it like
// declare context
Context siblingContext ;
then initialise it
.. onCreateView(...){
siblingContext = getContext();
context = getActvity();
}
you mistake in instantiate your adapter in line 24.change ListView siblingLVAdapter; to
SiblingsListViewAdapter siblingLVAdapter;
and use Context context =getActivity(); or Activity activity=getActivity(); in onAtach methode
I created a small application where I have a list of products and for each of the product I have an expiry time. If the user chooses to like a certain product(showTimerPost), the expiry time of the product will increase lets say 5 second. I tried it with a handler and it actually worked but my app started to run really slow maybe because it was changing the UI every second. I am really stuck with this problem for 1 month. Help will be appreciated.
package com.blueflair.incre;
import com.blueflair.incre.app.AppController;
import com.blueflair.incre.data.FeedItem;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.volley.toolbox.ImageLoader;
public class FeedListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
LocalUserData userLocalStore;
long postExpiry;
String timerFormat;
private int defaultPostIncrementation = 900000;
private List<FeedItem> feedItems;
boolean favourite;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
private long timeDiff;
private final List<ViewHolder> lstHolders;
private int avatarSize;
Handler handler = new Handler();
private Runnable timerRunnable = new Runnable() {
#Override
public void run() {
for (final ViewHolder holder : lstHolders) {
holder.showTimerPost.postDelayed(new Runnable() {
#Override
public void run() {
long currentTime = System.currentTimeMillis();
currentTime--;
holder.showTimerPost.setText(String.valueOf(holder.updateTimeRemaining(currentTime)));
notifyDataSetChanged();
}
}, 2000);
}
}
};
public FeedListAdapter(Activity activity, List<FeedItem> feedItems) {
this.activity = activity;
this.feedItems = feedItems;
lstHolders = new ArrayList<>();
}
#Override
public int getCount() {
return feedItems.size();
}
#Override
public Object getItem(int location) {
return feedItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.feed_item, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
final FeedItem item = feedItems.get(position);
holder = new ViewHolder();
userLocalStore = new LocalUserData(activity);
final User user = userLocalStore.getLoggedInUser();
postExpiry = item.getPostExpiry();
avatarSize = activity.getResources().getDimensionPixelSize(R.dimen.feed_avater_size);
holder.name = (TextView) convertView.findViewById(R.id.userFeedName);
holder.timestamp = (TextView) convertView
.findViewById(R.id.timestamp);
holder.statusMsg = (TextView) convertView
.findViewById(R.id.txtStatusMsg);
holder.profilePic = (ImageView) convertView
.findViewById(R.id.profilePic);
holder.profilePic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bundle args= new Bundle();
args.putInt("userId", item.getUserId());
Fragment profileViewFragment = new ProfileViewFragment();
profileViewFragment.setArguments(args);
FragmentTransaction ft = ((MainActivity)activity).getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_done, R.anim.slide_out_send);
ft.replace(R.id.container_body, profileViewFragment);
ft.addToBackStack(null);
ft.commit();
}
});
holder.feedImageView = (FeedImageView) convertView
.findViewById(R.id.feedImage1);
String username = "#"+item.getUserName();
holder.name.setText(username);
convertView.setTag(holder);
synchronized ( lstHolders) {
lstHolders.add(holder);
}
// Converting timestamp into x ago format
CharSequence timeAgo = DateUtils.getRelativeTimeSpanString(
Long.parseLong(item.getTimeCreated()),
System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS);
holder.timestamp.setText(timeAgo);
holder.showTimerPost = (Button) convertView.findViewById(R.id.showPostTimer);
handler.post(timerRunnable);
holder.showTimerPost.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
item.setIncrementToExpiry(50000);
notifyDataSetChanged();
}
});
// Chcek for empty status message
if (!TextUtils.isEmpty(item.getPostMessage())) {
holder.statusMsg.setText(item.getPostMessage());
holder.statusMsg.setVisibility(View.VISIBLE);
} else {
// status is empty, remove from view
holder.statusMsg.setVisibility(View.GONE);
}
// Feed image
if (item.getUserImage() != null) {
holder.feedImageView.setImageUrl(item.getUserImage(), imageLoader);
holder.feedImageView.setVisibility(View.VISIBLE);
holder.feedImageView
.setResponseObserver(new FeedImageView.ResponseObserver() {
#Override
public void onError() {
}
#Override
public void onSuccess() {
}
});
} else {
holder.feedImageView.setVisibility(View.GONE);
}
//Setting the timer adapter for the post and their respective contents
holder.setData(item);
return convertView;
}
private class ViewHolder {
FeedItem item;
public TextView name;
public TextView timestamp;
public TextView statusMsg;
public ImageView profilePic;
public FeedImageView feedImageView;
public Button showTimerPost;
public void setData(FeedItem item) {
this.item = item;
updateTimeRemaining(System.currentTimeMillis());
}
public String updateTimeRemaining(long currentTime) {
timeDiff = (item.getPostExpiry()+400000000) - currentTime;
if (timeDiff > 0) {
timerFormat = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(timeDiff),
TimeUnit.MILLISECONDS.toMinutes(timeDiff) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeDiff)),
TimeUnit.MILLISECONDS.toSeconds(timeDiff) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeDiff)));
showTimerPost.setText(timerFormat);
return timerFormat;
} else {
//Delete feed items when post is expired
showTimerPost.setText("Expired!");//only to explimify
}
return timerFormat;
}
}
}