I have created an application that can show call logs. I am using LazyAdapter class. I am showing an icon according to the call type: Missed / Incoming / Outgoing. This part is not working properly. The display of text like name, number, date and time is showing just fine except the Call type?
Here is what I am trying to do:
public class LazyAdapter extends BaseAdapter
{
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d)
{
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount()
{
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.callist, null);
TextView name = (TextView)vi.findViewById(R.id.name);
TextView number = (TextView)vi.findViewById(R.id.phone_number);
TextView date = (TextView)vi.findViewById(R.id.date);
TextView time = (TextView)vi.findViewById(R.id.time);
TextView duration = (TextView)vi.findViewById(R.id.duration);
ImageView callType = (ImageView)vi.findViewById(R.id.calType);
ImageView clock = (ImageView)vi.findViewById(R.id.Clock);
HashMap<String, String> pro = new HashMap<String, String>();
pro = data.get(position);
if((pro.get(ListOfCall.contactName)!=null))
{
name.setText(pro.get(ListOfCall.contactName));
}
else
{
name.setText("Unknown");
}
number.setText(pro.get(ListOfCall.phone));
date.setText(pro.get(ListOfCall.DateOfCall));
time.setText(pro.get(ListOfCall.TimeOfCall));
String type = pro.get(ListOfCall.typeofCall);
if(type.equalsIgnoreCase("OUTGOING"))
{
callType.setImageResource(R.drawable.outgoing);
duration.setText(pro.get(ListOfCall.durationOfCall));
}
else if(type.equalsIgnoreCase("INCOMING"))
{
callType.setImageResource(R.drawable.incoming);
duration.setText(pro.get(ListOfCall.durationOfCall));
}
else if(type.equalsIgnoreCase("MISSED"))
{
callType.setImageResource(R.drawable.missed);
duration.setVisibility(4);
clock.setVisibility(4);
}
return vi;
}
}
I am not really sure where the problem is coming because I am able get correct results in the arraylist called data in the top. Things change when I move the arraylist to Hashmap called pro.
Again the values are coming up properly except the call type and it's corresponding images are not coming up.
Can somebody help me out to fix this up?
Figured out the conditions that were in LazyAdapter class didn't work as required. Removed the condition and added them in before class that was sending values to LazyAdapter class.
Works fine now!!
Thanks!
Related
i think that this can be done, but maybe im wrong (Im sure im wrong). I have this adapter that sometimes uses a List of Class1 and in other moments uses a list of Class2. So, can i do TWO differents constructors where un the first one i use List1 and in the other one i use the List2?
public class SpinnerAdapter extends BaseAdapter {
private List<String> listaDeTexto;
private Activity activity;
private LayoutInflater layoutInflater;
private List<MetodoDePago> listaMetodosDePago;
private List<Banco> listaDeBancos;
public SpinnerAdapter(List<String> listaDeTexto, Activity activity, List<MetodoDePago> listaMetodosDePago) {
this.listaDeTexto = listaDeTexto;
this.activity = activity;
this.layoutInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.listaMetodosDePago = listaMetodosDePago;
}
public SpinnerAdapter(List<String> listaDeTexto, Activity activity, List<Banco> listaDeBancos) {
this.listaDeTexto = listaDeTexto;
this.activity = activity;
this.layoutInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.listaDeBancos = listaDeBancos;
}
#Override
public int getCount() {
return listaDeTexto.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null){
view = layoutInflater.inflate(R.layout.spinner_custom,null);
}
TextView textView = view.findViewById(R.id.textViewSpinner);
textView.setText(listaDeTexto.get(position));
ImageView imageView = view.findViewById(R.id.imgViewSpinner);
Glide.with(view)
.load(listaMetodosDePago.get(position).getThumbnail())
.into(imageView);
return view;
}
}
Due to type erasure in Java, you are basically declaring two constructors which look like, SpinnerAdapter(List l1, Activity a, List l2) { } to Java.
A simple solution would be to create one constructor and add a type argument. So, something like, SpinnerAdapter(List l1, Activity a, List l2, int type) { }.
You can then check the type value in the constructor and the getView(...) method to initialize your variables as needed.
I am making an Android chat app that uses Cloud Firebase. In populating the listview with messages, I want to use two layouts, one for the incoming messages, and one for the going out messages. When following a tutorial that did something like this,
( http://www.devexchanges.info/2016/12/simple-chat-application-using-firebase.html )
they make their own messageAdapter class which introduces a getView function that will return one of the two views depending on the message. in the constructor for this class though, the super() statement is not working for me. here is the constructor:
public MessageAdapter(Lobby activity, Class<ChatMessage> modelClass, int modelLayout, DatabaseReference ref) {
super(activity, modelClass, modelLayout, ref);
this.activity = activity;
}
this is exactly like the tutorial uses it, but for some reason in the context of my own application it is not working. Is there something I have to do with the FirebaseListAdapter class to allow this action? Any help would be appreciated, if you need to see any of the other code in my project I'll be happy to edit to include it. Thanks.
Try using a RecyclerView and RecyclerView.Adapter instead of a FirebaseListAdapter, like this:
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder> {
private static final int CHAT_END = 1;
private static final int CHAT_START = 2;
private List<Chat> mDataSet;
private String mId;
/**
* Called when a view has been clicked.
*
* #param dataSet Message list
* #param id Device id
*/
ChatAdapter(List<Chat> dataSet, String id) {
mDataSet = dataSet;
mId = id;
}
#Override
public ChatAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
if (viewType == CHAT_END) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_chat_end, parent, false);
} else {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_chat_start, parent, false);
}
return new ViewHolder(v);
}
#Override
public int getItemViewType(int position) {
if (mDataSet.get(position).getId().equals(mId)) {
return CHAT_END;
}
return CHAT_START;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Chat chat = mDataSet.get(position);
holder.mTextView.setText(chat.getMessage());
}
#Override
public int getItemCount() {
return mDataSet.size();
}
/**
* Inner Class for a recycler view
*/
class ViewHolder extends RecyclerView.ViewHolder {
TextView mTextView;
ViewHolder(View v) {
super(v);
mTextView = (TextView) itemView.findViewById(R.id.tvMessage);
}
}
}
Please see more at https://github.com/thaleslima/firebase-chat-sample.
I have the following problem:
I am trying to load some data from firebase and after the data is loaded and stored in a HashMap I call the "updateAdapter" function (declared in the adapter below) and although the data has being changed the ListView doesn't refresh until some later random-(IMO) moment. I read couple of posts related to my problem and tried different solutions suggested there but they don't fix my problem. And by the way - Yes, I checked if the adapter loses the reference to the list and it doesn't.
My adapter looks like this:
public class NoteAdapterHashMap extends BaseAdapter{
private ArrayList mData = new ArrayList();
public NoteAdapterHashMap(Map<String, Note> map) {
mData.addAll(map.entrySet());
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Map.Entry<String, Note> getItem(int position) {
return (Map.Entry) mData.get(position);
}
#Override
public long getItemId(int position) {
// TODO implement logic with ID
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final View result;
if (convertView == null) {
result = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_note_listview, parent, false);
} else {
result = convertView;
}
Note note = getItem(position).getValue();
if(note!=null){
TextView title = (TextView) result.findViewById(R.id.list_note_title);
TextView date = (TextView) result.findViewById(R.id.list_note_date);
TextView content = (TextView) result.findViewById(R.id.list_note_content);
title.setText(note.getmTitle());
date.setText(note.getDateFormatted(parent.getContext()));
content.setText(note.getmContent());
if(note.getmContent().length()>50){
content.setText(note.getmContent().substring(0,50));
}
}
return result;
}
public void updateAdapter(HashMap<String,Note> map){
this.mData.clear();
this.mData.addAll(map.entrySet());
this.notifyDataSetChanged();
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
super.registerDataSetObserver(observer);
}
}
Thanks in advance !
I am trying to display detailed Product information in an custom Listview with two TextViews per row for the key/value pair. The data is displayed correct. I also colored every second line different.
And there is my Problem. If I scroll up and down the different colored rows change their color and remain in this state. The data is not affected from this problem. Just the backroundcolor of the TextViews. I use the ViewHolder Pattern but this did not change anything. I added the code of the adapter. I think thats enough. Have you any idea?
Screenshot of the problem:
Code:
public class ProductDetailAdapter extends BaseAdapter {
private LinkedHashMap<String,String> list;
private Context context;
public ProductDetailAdapter(Context c, LinkedHashMap<String,String> list){
super();
this.context = c;
this.list=list;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ProductDetailAdapter.ViewHolder viewHolder;
if(convertView == null){
convertView=inflater.inflate(R.layout.product_detail_data_row,null);
viewHolder = new ViewHolder();
viewHolder.textViewKey = (TextView) convertView.findViewById(R.id.productDataKey);
viewHolder.textViewValue = (TextView) convertView.findViewById(R.id.productDataValue);
convertView.setTag(viewHolder);
}else {
viewHolder = (ProductDetailAdapter.ViewHolder) convertView.getTag();
}
viewHolder.textViewKey.setText((String)list.keySet().toArray()[position]);
viewHolder.textViewValue.setText(list.get(list.keySet().toArray()[position]));
if(position % 2 == 0){
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
}
return convertView;
}
private static class ViewHolder {
public TextView textViewKey;
public TextView textViewValue;
public ViewHolder(){};
}
}
That happens because the rows are being recycled. It's a common problem.
You can solve it by doing:
if(position % 2 == 0){
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
} else {
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite1)); //Or the color that you want for odd rows
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite1)); //Or the color that you want for odd rows
}
Try this:
super( c, 0, list );
instead of this:
super();
Once you pass the data source to the adapter you no longer need :
getCount
getItem
getItemId
please refer this link and link2 and link3 these will work for you
I'm trying to populate a ListView with an ArrayList> using a base adapter. The ArrayList is populated by a database, and it is possible for the database to have no entries, and thus a empty ArrayList, for example when the app is launched for the first time. While the ArrayList is empty, I receive a non de-script "java.lang.RuntimeException: Unable to start activity ComponentInfo ... java.lang.NullPointerException".
My onCreate method looks like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.samples_list_layout);
mContext = getApplicationContext();
lv = getListView();
list = myDatabase.getInstance(mContext).getAllSamples();
sa = new SamplesAdapter(this, list);
lv.setAdapter(sa);
registerForContextMenu(lv);
}
Setting lv.setAdapter(null) will get the app to display the empty list view I have set up. However, when I leave it up to the BaseAdapter, I get the error.
I've followed the 2 Android List8.java and List14.java examples, and either way give the same results.
My BaseAdapter class looks like this:
public class SamplesAdapter extends BaseAdapter {
private static final String SAMPLE_NAME_COL = "name";
private static final String SAMPLE_HOST_COL = "host";
private static final String SAMPLE_ICON_COL = "icon";
private static final String SAMPLE_MODIFIED_STAMP_COL = "moddate";
private Context mContext;
private ArrayList<HashMap<String, String>> samples = new ArrayList<HashMap<String, String>>();
public SamplesAdapter(Context c, ArrayList<HashMap<String, String>> list){
mContext = c;
samples = list;
}
public int getCount() {
return samples.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.samples_row_layout, parent, false);
TextView name = (TextView) v.findViewById(R.id.samples_name);
name.setText(samples.get(position).get(SAMPLE_NAME_COL));
TextView host = (TextView) v.findViewById(R.id.samples_host);
host.setText(samples.get(position).get(SAMPLE_HOST_COL));
TextView moddate = (TextView) v.findViewById(R.id.samples_mod_stamp);
moddate.setText(samples.get(position).get(SAMPLE_MODIFIED_STAMP_COL));
return v;
}
}
I should also note that the ListView properly displays items when there is something to show. It only fails when the ArrayList is empty. Also, I'm using Android 2.2 (Not the greatest, I know). Any help would be greatly appreciated.
let getCount return 0, in orded to avoid the NPE:
public int getCount() {
return (samples == null) ? 0 : samples.size();
}