I am working on a learning Android application (PersistAlarm, I call it) where I can set an alarm. The application's first activity is a button with ListView where the user can add alarms to the application. The alarm is set in the second activity and it populates the DB in the backend.
Once the alarm is set, it returns to the first activity (PersistAlarm.java) where the list of alarms is populated.
The problem is that till now, I was able to get the list of alarms. Suddenly, only the first entry in the alarms table is now visible. Other entries arent displayed. Strange!
Can anyone tell me where I am going wrong?
Here's the PersistAlarm Activity XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".PersistAlarm" >
<Button
android:id="#+id/buttonAddAlarm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Entry" />
<ListView
android:id="#+id/alarmListV"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
Here's the PersistAlarm.java code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_persist_alarm);
final AlarmAdapter alarmAdapt;
final ListView mainAlarmView;
final Context context = this;
Button alarmAdd = (Button) findViewById(R.id.buttonAddAlarm);
mainAlarmView = (ListView) findViewById(R.id.alarmListV);
alarmAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(context, AddEditAlarm.class);
startActivity(intent);
}
});
List<PAlarm> alarmList = db.getAllAlarms();
Log.d("LIST COUNT" , String.valueOf(alarmList.size()));
alarmAdapt = new AlarmAdapter(PersistAlarm.this, R.id.alarmListV, alarmList);
mainAlarmView.setAdapter(alarmAdapt);
}
Here's my PAlarm object that acts as the foundation object for the Application:
public class PAlarm {
int _id;
String _eventName;
String _eventDate;
String _eventTime;
String _type;
public PAlarm() {
}
public PAlarm(int id, String eventName, String eventDate, String eventTime, String type) {
this._id = id;
this._eventName = eventName;
this._eventDate = eventDate;
this._eventTime = eventTime;
this._type = type;
}
public PAlarm(String eventName, String eventDate, String eventTime, String type) {
this._eventName = eventName;
this._eventDate = eventDate;
this._eventTime = eventTime;
this._type = type;
}
public int get_id() {
return _id;
}
public void set_id(int _id) {
this._id = _id;
}
public String get_eventName() {
return _eventName;
}
public void set_eventName(String _eventName) {
this._eventName = _eventName;
}
public String get_eventDate() {
return _eventDate;
}
public void set_eventDate(String _eventDate) {
this._eventDate = _eventDate;
}
public String get_eventTime() {
return _eventTime;
}
public void set_eventTime(String _eventTime) {
this._eventTime = _eventTime;
}
public String get_type() {
return _type;
}
public void set_type(String _type) {
this._type = _type;
}
#Override
public String toString() {
return this._id + ". " + this._eventName + " - " + this._eventDate + " - " + this._eventTime;
}
This is my custom Adapter to render the ListView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/alarmNameTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24dip" />
<TextView
android:id="#+id/alarmDateTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="9dip" />
</LinearLayout>
Also, my Custom Adapter's java code:
public class AlarmAdapter extends ArrayAdapter<PAlarm> {
private List<PAlarm> alarms;
private Activity activity;
public AlarmAdapter(Activity a, int textViewId, List<PAlarm> alms) {
super(a, textViewId, alms);
this.alarms = alms;
this.activity = a;
}
public static class ViewHolder {
public TextView alarmView;
public TextView alarmDateTimeView;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolder holder;
if (v == null) {
LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.alarm_item, null);
holder = new ViewHolder();
holder.alarmView = (TextView) v.findViewById(R.id.alarmNameTV);
holder.alarmDateTimeView = (TextView) v.findViewById(R.id.alarmDateTime);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
final PAlarm alarm = alarms.get(position);
if (alarm != null) {
holder.alarmView.setText(alarm.get_eventName());
holder.alarmDateTimeView.setText(alarm.get_eventDate() + " (" + alarm.get_eventTime() + ")" );
}
}
return v;
}
Would appreciate some help here. Thanks
try changing your getView():
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolder holder;
if (v == null) {
LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.alarm_item, null);
holder = new ViewHolder();
holder.alarmView = (TextView) v.findViewById(R.id.alarmNameTV);
holder.alarmDateTimeView = (TextView) v.findViewById(R.id.alarmDateTime);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
final PAlarm alarm = alarms.get(position);
if (alarm != null) {
holder.alarmView.setText(alarm.get_eventName());
holder.alarmDateTimeView.setText(alarm.get_eventDate() + " (" + alarm.get_eventTime() + ")" );
}
return v;
}
Explaination:
In ListView views are recycled if view coming in getView() is null it means view is not recycled and we have to initialize it; which we do in if condition. if view is not null that means it is recycled and we just have to change the data for that view.
so view is recycled or not we have to set data. so data setting code should be outside if...else
Related
This is my wordAdapter. It is not showing any result when I open the Fragment. Please help me as I am a novice android developer. The Fragment page is empty and it is also not showing any error while running. So, please tell what am I missing and what is the problem in this code.
public class wordAdapter extends ArrayAdapter<word> {
private Context context;
private List<word> wrd;
private SharedPreference sharedPreference;
public wordAdapter(Context context, List<word> wrd) {
super(context, R.layout.item, wrd);
this.context = context;
this.wrd = wrd;
sharedPreference = new SharedPreference();
}
private class ViewHolder {
TextView productNameTxt;
TextView productTypeTxt;
ImageView favoriteImg;
}
#Override
public int getCount() {
return wrd.size();
}
#Override
public word getItem(int position) {
return wrd.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item, null);
holder = new ViewHolder();
holder.productNameTxt = (TextView) convertView
.findViewById(R.id.carname);
holder.productTypeTxt = (TextView) convertView
.findViewById(R.id.cartype);
holder.favoriteImg = (ImageView) convertView
.findViewById(R.id.favu);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
word wrdn = (word) getItem(position);
holder.productNameTxt.setText(wrdn.getName());
holder.productTypeTxt.setText(wrdn.getType());
/*If a product exists in shared preferences then set heart_red drawable
* and set a tag*/
if (checkFavoriteItem(wrdn)) {
holder.favoriteImg.setImageResource(R.drawable.fav);
holder.favoriteImg.setTag("red");
} else {
holder.favoriteImg.setImageResource(R.drawable.unfav);
holder.favoriteImg.setTag("grey");
}
return convertView;
}
/*Checks whether a particular product exists in SharedPreferences*/
private boolean checkFavoriteItem(word checkwrdn) {
boolean check = false;
List<word> favorites = sharedPreference.getFavorites(context);
if (favorites != null) {
for (word wrdn : favorites) {
if (wrdn.equals(checkwrdn)) {
check = true;
break;
}
}
}
return check;
}
#Override
public void add(word wrdn) {
super.add(wrdn);
wrd.add(wrdn);
notifyDataSetChanged();
}
#Override
public void remove(word wrdn) {
super.remove(wrdn);
wrd.remove(wrdn);
notifyDataSetChanged();
}
}
This is my word file.
public class word {
private String name;
private String type;
public word(String name, String type) {
super();
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
}
This is my Fragment file with the data.
public class Cars extends android.support.v4.app.Fragment implements
AdapterView.OnItemClickListener,
AdapterView.OnItemLongClickListener {
public static final String ARG_PAGE = "ARG_PAGE";
public static Favourites newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
Favourites fragment = new Favourites();
fragment.setArguments(args);
return fragment;
}
Activity activity;
ListView productListView;
List<word> wrds;
wordAdapter wrdAdapter;
SharedPreference sharedPreference;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = getActivity();
sharedPreference = new SharedPreference();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list, container,
false);
findViewsById(view);
setProducts();
wrdAdapter = new wordAdapter(activity, wrds);
productListView.setAdapter(wrdAdapter);
productListView.setOnItemClickListener(this);
productListView.setOnItemLongClickListener(this);
return view;
}
private void setProducts() {
word product1 = new word("Lamborghini Huracan", "Sport");
word product2 = new word("Lamborghini Aventador", "Sport");
word product3 = new word("Jaguar XF", "Luxury Sedan");
word product4 = new word("Audi A4", "Luxury Sedan");
word product5 = new word("Ferrari 488", "Sport");
word product6 = new word("BMW i8", "Hybrid Sport");
word product7 = new word("Audi TT", "Sport");
wrds = new ArrayList<word>();
wrds.add(product1);
wrds.add(product2);
wrds.add(product3);
wrds.add(product4);
wrds.add(product5);
wrds.add(product6);
wrds.add(product7);
}
private void findViewsById(View view) {
productListView = (ListView) view.findViewById(R.id.list_product);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
word product = (word) parent.getItemAtPosition(position);
Toast.makeText(activity, product.toString(), Toast.LENGTH_LONG).show();
}
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View view,
int position, long arg3) {
ImageView button = (ImageView) view.findViewById(R.id.favu);
String tag = button.getTag().toString();
if (tag.equalsIgnoreCase("grey")) {
sharedPreference.addFavorite(activity, wrds.get(position));
button.setTag("red");
button.setImageResource(R.drawable.fav);
} else {
sharedPreference.removeFavorite(activity, wrds.get(position));
button.setTag("grey");
button.setImageResource(R.drawable.unfav);
}
return true;
}
#Override
public void onResume() {
getActivity().setTitle(R.string.app_name);
getActivity().getActionBar().setTitle(R.string.app_name);
super.onResume();
}
}
This is my list view.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EDEDED" >
<ListView
android:id="#+id/list_product"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:dividerHeight="10dp"
android:drawSelectorOnTop="true"
android:footerDividersEnabled="false"
android:padding="10dp"
android:scrollbarStyle="outsideOverlay" >
</ListView>
</RelativeLayout>
This is the items view.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants" >
<RelativeLayout
android:id="#+id/pdt_layout_item"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/carname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6dp" />
<TextView
android:id="#+id/cartype"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/carname"
android:padding="6dp" />
<ImageView
android:id="#+id/favu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="3dp"
android:background="#null" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="#id/pdt_layout_item"/>
</RelativeLayout>
I'm trying to populate a listview with the id android.id/list with some xml data.. The data is successfully requested and I get no errors when passing it to my Lazy Adapter and setting it to the listview.. Can somebody help me?
The request:
private void requestFeed() {
SimpleXmlRequest<StationList> simpleRequest = new SimpleXmlRequest<StationList>(Request.Method.GET, url, StationList.class,
new Response.Listener<StationList>()
{
#Override
public void onResponse(StationList response) {
list = response.getStationList();
buildFeed();
if(mSplashDialog != null) {
removeSplashScreen();
} else {
setReloadFeedButtonState(false);
}
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error Object
Log.d("TESTE", error.toString());
}
}
);
simpleRequest.setTag(SIMPLE_TAG);
queue = Volley.newRequestQueue(this);
queue.add(simpleRequest);
}
The buildFeed:
private void buildFeed() {
if(stations == null) {
stations = (ListView) findViewById(android.R.id.list);
adapter = new LazyAdapter(this, list);
stations.setAdapter(adapter);
}
adapter.notifyDataSetChanged();
}
The adapter:
public class LazyAdapter extends BaseAdapter {
private List<Station> stations;
private static LayoutInflater inflater = null;
public LazyAdapter(Activity activity, List<Station> stations) {
this.stations = stations;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return stations.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.list_row, null);
TextView name = (TextView) vi.findViewById(R.id.station_name);
TextView ct = (TextView) vi.findViewById(R.id.station_ct);
TextView cl = (TextView) vi.findViewById(R.id.station_cl);
Station tmp = stations.get(position);
name.setText(tmp.get_name());
ct.setText(tmp.get_ct());
cl.setText(tmp.get_lc().toString());
return vi;
}
}
the xml of the activity
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/MainActivityLL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="me...MainActivity" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:divider="#color/list_divider"
android:dividerHeight="1dp"
android:layout_weight="1"
android:listSelector="#drawable/list_row_selector" />
<TextView
android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="#android:style/TextAppearance.Medium"
android:text="#string/emptyList"
android:gravity="center" />
I've checked the stations list that comes in the response and is not empty.. I have all the data I need, but the listview is always showing the empty message from the textview with id android.id/empty ..
Remove android:id="#android:id/list"
Replace it with android:id="#+id/list"
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:divider="#color/list_divider"
android:dividerHeight="1dp"
android:layout_weight="1"
android:listSelector="#drawable/list_row_selector" />
Try to Use ViewHolder design pattern when you make custom adapter :
public class LazyAdapter extends BaseAdapter {
private List<Station> stations;
private Context context;
public LazyAdapter(Context context, List<Station> stations) {
this.stations = stations;
this.context=context;
}
public int getCount() {
return stations.size();
}
public Object getItem(int position) {
return stations.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null){
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.list_row, null);
holder.name = (TextView) convertView.findViewById(R.id.station_name);
holder.ct = (TextView) convertView.findViewById(R.id.station_ct);
holder.cl = (TextView) convertView.findViewById(R.id.station_cl);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.name.setText(stations.get(position).get_name());
holder.ct.setText(stations.get(position).get_ct());
holder.cl.setText(stations.get(position).get_lc().toString());
return convertView;
}
class ViewHolder{
TextView name;
TextView ct;
TextView cl;
}
}
I'm learning Android SDK and I need some advices.
I have custom ListView with BaseAdapter and I want to implement some new feature - Favorite Button.
What I want to do is, when I press the Favorite Button, ListItem goes to the beginning of the list, Favorite image change and all that stuff will be saved in the SharedPrefs.
Someone tell me what I need to do, to make it works?
my existing code:
row.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/layout_element_list"
>
<ImageView
android:id="#+id/icon"
android:layout_width="150dp"
android:padding="5dp"
android:layout_height="150dp"
android:layout_marginLeft="4px"
android:layout_marginRight="10px"
android:layout_marginTop="4px"
android:src="#drawable/radio" >
</ImageView>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/label"
android:paddingTop="20dp"
android:layout_gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:textAlignment="center"
android:text="RadioName"
android:textColor="#color/color1"
android:textSize="30dp" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
<TextView
android:id="#+id/label2"
android:layout_gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_weight="1"
android:layout_height="fill_parent"
android:textAlignment="center"
android:text="Description.."
android:textColor="#color/color1"
android:textSize="15dp" />
<ImageView
android:id="#+id/favButton"
android:layout_weight="1"
android:layout_width="fill_parent"
android:padding="5dp"
android:layout_height="fill_parent"
android:layout_marginLeft="4px"
android:layout_marginRight="10px"
android:layout_marginTop="4px"
android:src="#drawable/fav_off" >
</ImageView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
BaseAdapter class:
public class RadioAdapter extends BaseAdapter
{
ArrayList<RadioStation> myList = new ArrayList<RadioStation>();
LayoutInflater inflater;
Context context;
public RadioAdapter(Context context, ArrayList<RadioStation> myList) {
this.myList = myList;
this.context = context;
inflater = LayoutInflater.from(this.context);
}
#Override
public int getCount() {
return myList.size();
}
#Override
public RadioStation getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyViewHolder mViewHolder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.activity_menu_row, null);
mViewHolder = new MyViewHolder();
convertView.setTag(mViewHolder);
} else {
mViewHolder = (MyViewHolder) convertView.getTag();
}
mViewHolder.tvTitle = detail(convertView, R.id.label, myList.get(position).getTitle());
mViewHolder.tvDesc = detail(convertView, R.id.label2, myList.get(position).getDescription());
mViewHolder.ivIcon = detail(convertView, R.id.icon, myList.get(position).getImgResId());
return convertView;
}
private TextView detail(View v, int resId, String text) {
TextView tv = (TextView) v.findViewById(resId);
tv.setText(text);
return tv;
}
private ImageView detail(View v, int resId, int icon) {
ImageView iv = (ImageView) v.findViewById(resId);
iv.setImageResource(icon); //
return iv;
}
private class MyViewHolder {
TextView tvTitle, tvDesc;
ImageView ivIcon;
}
}
RadioStation class:
public class RadioStation
{
public String title;
public String description;
public int imgResId;
//getters and setters
public static Comparator<RadioStation> comparatorByRadioName = new Comparator<RadioStation>()
{
#Override
public int compare(RadioStation radioStation, RadioStation radioStation2)
{
String name1 = radioStation.getTitle().toLowerCase();
String name2 = radioStation2.getTitle().toLowerCase();
return name1.compareTo(name2);
}
};
}
ActivityListView:
public class ActivityMenuList extends Activity implements AdapterView.OnItemClickListener
{
private ListView lvDetail;
private Context context = ActivityMenuList.this;
private ArrayList <RadioStation> myList = new ArrayList <RadioStation>();
private String[] names = new String[] { "one", "two", "three" };
private String[] descriptions = new String[] { "notset", "notset", "notset"};
private int[] images = new int[] { R.drawable.one, R.drawable.two, R.drawable.three };
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getWindow().setBackgroundDrawableResource(R.drawable.bg1);
setContentView(R.layout.activity_menu_list);
lvDetail = (ListView) findViewById(R.id.list);
lvDetail.setOnItemClickListener(this);
getDataInList();
lvDetail.setAdapter(new RadioAdapter(context, myList));
}
private void getDataInList() {
for(int i=0;i<3;i++) {
RadioStation ld = new RadioStation();
ld.setTitle(names[i]);
ld.setDescription(descriptions[i]);
ld.setImgResId(images[i]);
myList.add(ld);
}
Collections.sort(myList, RadioStation.comparatorByRadioName);
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
{
String item = names[i];
Intent e = new Intent(ActivityMenuList.this, ActivityRadioStation.class);
Bundle data = new Bundle();
data.putString("radiostation",item);
e.putExtras(data);
startActivity(e);
}
}
That's a lot of changes you have to do. Let's start with the basic.
Add a boolean to your RadioStation for the favorite state.
public boolean isFavorite;
Next on your getView add the favorite button click listener(add its reference to the viewholder too, but let's keep it simple this time)
public class RadioAdapter extends BaseAdapter
{
ArrayList<RadioStation> myList = new ArrayList<RadioStation>();
LayoutInflater inflater;
Context context;
ListView mListview;
public RadioAdapter(Context context, ArrayList<RadioStation> myList, ListView list) {
this.myList = myList;
this.context = context;
mListView = list;
inflater = LayoutInflater.from(this.context);
}
#Override
public int getCount() {
return myList.size();
}
#Override
public RadioStation getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
MyViewHolder mViewHolder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.activity_menu_row, null);
mViewHolder = new MyViewHolder();
convertView.setTag(mViewHolder);
} else {
mViewHolder = (MyViewHolder) convertView.getTag();
}
mViewHolder.tvTitle = detail(convertView, R.id.label, myList.get(position).getTitle());
mViewHolder.tvDesc = detail(convertView, R.id.label2, myList.get(position).getDescription());
mViewHolder.ivIcon = detail(convertView, R.id.icon, myList.get(position).getImgResId());
convertView.findViewById(R.id.favButton).setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
myList.get(position).isFavorite=! myList.get(position).isFavorite;
//reorder mlist
notifyDataSetChanged();
//mListView. smoothscroll here
}
});
((ImageView) convertView.findViewById(R.id.favButton)).setImageResource(myList.get(position).isFavorite?R.drawable.favoriteOn:R.drawable.favoriteOff);
return convertView;
}
private TextView detail(View v, int resId, String text) {
TextView tv = (TextView) v.findViewById(resId);
tv.setText(text);
return tv;
}
private ImageView detail(View v, int resId, int icon) {
ImageView iv = (ImageView) v.findViewById(resId);
iv.setImageResource(icon); //
return iv;
}
private class MyViewHolder {
TextView tvTitle, tvDesc;
ImageView ivIcon;
}
}
I left commented what you should do on the listener. You should be able to continue from here.
When you create your adapter pass the list as the last parameter on the constructor.
Edited: Removed interface. No need to use it here.
I get my navigation drawer in a proper way when I first launch the app. The problem comes when I scroll down the drawer. Items beging to disappear and some of them even swap places. I've tried to find what is wrong but I canĀ“t. Hope you could help me.
I've updated my code using getItemViewType(int) and getViewTypeCount() but the problem still there when recycling the views.
I leave you some piece of code here:
NEW CODE
public class NavDrawerListAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_HEADER = 1;
private static final int TYPE_SWITCH = 2;
private static final int TYPE_MAX_COUNT = 3;
private Context mContext;
private ArrayList<NavDrawerItem> navDrawerItems;
LayoutInflater inflater;
public NavDrawerListAdapter(Context context, ArrayList<NavDrawerItem> navDrawerItems){
this.mContext = context;
this.navDrawerItems = navDrawerItems;
inflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return navDrawerItems.size();
}
#Override
public Object getItem(int position) {
return navDrawerItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
//return super.getItemViewType(position);
if((!navDrawerItems.get(position).getHeaderVisibility())
&&(!navDrawerItems.get(position).getSwitchVisibility()))
return TYPE_ITEM;
else if((navDrawerItems.get(position).getHeaderVisibility())
&&(!navDrawerItems.get(position).getSwitchVisibility()))
return TYPE_HEADER;
else if((!navDrawerItems.get(position).getHeaderVisibility())
&&(navDrawerItems.get(position).getSwitchVisibility()))
return TYPE_SWITCH;
else return TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
//return super.getViewTypeCount();
return TYPE_MAX_COUNT;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("NavDrawerAdapterTest: ", "getView: " + position + " " + convertView);
Log.d("NavDrawerAdapter: ", "0");
ViewHolderItem viewHolder;
int type = getItemViewType(position);
Log.d("NavDrawerAdapter: ", "1");
if (convertView == null) {
Log.d("NavDrawerAdapter: ", "2a");
/*LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);*/
viewHolder = new ViewHolderItem();
switch (type) {
case TYPE_ITEM:
convertView = inflater.inflate(R.layout.drawer_list_item, null);
viewHolder.textViewTitleItem = (TextView) convertView.findViewById(R.id.title);
viewHolder.imageViewIconItem = (ImageView) convertView.findViewById(R.id.icon);
viewHolder.imageViewIconItem.setImageResource(navDrawerItems.get(position).getIcon());
viewHolder.textViewTitleItem.setText(navDrawerItems.get(position).getTitle());
break;
case TYPE_HEADER:
convertView = inflater.inflate(R.layout.drawer_list_item_header, null);
viewHolder.textViewHeaderItem = (TextView) convertView.findViewById(R.id.drawerHeader);
viewHolder.dividerViewItem = (View) convertView.findViewById(R.id.drawerView);
viewHolder.textViewHeaderItem.setText(navDrawerItems.get(position).getHeader());
break;
case TYPE_SWITCH:
convertView = inflater.inflate(R.layout.drawer_list_item_switch, null);
break;
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolderItem)convertView.getTag();
}
return convertView;
}
static class ViewHolderItem {
TextView textViewTitleItem;
ImageView imageViewIconItem;
TextView textViewHeaderItem;
View dividerViewItem;
}
}
ORIGINAL CODE
NavDrawerItem.java
public class NavDrawerItem {
private String title;
private int icon;
private String header;
private boolean isHeader;
public NavDrawerItem(){}
public NavDrawerItem(String title, int icon){
this.title = title;
this.icon = icon;
this.isHeader = false;
}
public NavDrawerItem(String header) {
this(null, 0);
this.header = header;
this.isHeader = true;
}
public String getTitle(){
return this.title;
}
public int getIcon(){
return this.icon;
}
public String getHeader() {
return header;
}
public boolean getHeaderVisibility() {
return isHeader;
}
public void setTitle(String title){
this.title = title;
}
public void setIcon(int icon){
this.icon = icon;
}
public void setHeader(String header) {
this.header = header;
}
public void setHeaderVisibility(boolean isHeader) {
this.isHeader = isHeader;
}
}
NavDrawerListAdapter.java
public class NavDrawerListAdapter extends BaseAdapter {
private Context context;
private ArrayList<NavDrawerItem> navDrawerItems;
public NavDrawerListAdapter(Context context, ArrayList<NavDrawerItem> navDrawerItems){
this.context = context;
this.navDrawerItems = navDrawerItems;
}
#Override
public int getCount() {
return navDrawerItems.size();
}
#Override
public Object getItem(int position) {
return navDrawerItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("NavDrawerAdapter: ", "0");
ViewHolderItem viewHolder;
Log.d("NavDrawerAdapter: ", "1");
if (convertView == null) {
Log.d("NavDrawerAdapter: ", "2a");
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
viewHolder = new ViewHolderItem();
convertView = inflater.inflate(R.layout.drawer_list_item_test, null);
viewHolder.textViewTitleItem = (TextView) convertView.findViewById(R.id.title);
viewHolder.imageViewIconItem = (ImageView) convertView.findViewById(R.id.icon);
viewHolder.textViewHeaderItem = (TextView) convertView.findViewById(R.id.drawerHeader);
viewHolder.dividerViewItem = (View) convertView.findViewById(R.id.drawerView);
convertView.setTag(viewHolder);
} else {
Log.d("NavDrawerAdapter: ", "2b");
viewHolder = (ViewHolderItem) convertView.getTag();
}
if(navDrawerItems.get(position).getHeaderVisibility()) {
viewHolder.textViewTitleItem.setVisibility(TextView.INVISIBLE);
viewHolder.imageViewIconItem.setVisibility(ImageView.INVISIBLE);
viewHolder.textViewHeaderItem.setText(navDrawerItems.get(position).getHeader());
Log.d("NavDrawerAdapter: ", "3a");
} else {
viewHolder.textViewHeaderItem.setVisibility(TextView.INVISIBLE);
viewHolder.dividerViewItem.setVisibility(View.INVISIBLE);
viewHolder.imageViewIconItem.setImageResource(navDrawerItems.get(position).getIcon());
viewHolder.textViewTitleItem.setText(navDrawerItems.get(position).getTitle());
Log.d("NavDrawerAdapter: ", "3b");
}
return convertView;
}
static class ViewHolderItem {
TextView textViewTitleItem;
ImageView imageViewIconItem;
TextView textViewHeaderItem;
View dividerViewItem;
}
}
EDIT: drawer_list_item_test.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#drawable/list_selector">
<ImageView
android:id="#+id/icon"
android:layout_width="25dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:contentDescription="#string/desc_list_item_icon"
android:src="#drawable/ic_home"
android:layout_centerVertical="true" />
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toRightOf="#id/icon"
android:minHeight = "48dp"
android:textSize = "16sp"
android:textColor="#color/list_item_title"
android:gravity="center_vertical"
android:paddingRight="40dp"/>
<TextView
android:id="#+id/drawerHeader"
android:layout_above="#id/drawerView"
android:layout_marginLeft="12dp"
android:layout_marginTop="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textAllCaps="true"
android:textColor="#color/list_item_title" />
<View
android:id="#+id/drawerView"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginBottom="1dp"
android:layout_marginTop="2dp"
android:background="#color/list_background_pressed" />
</RelativeLayout>
You have trouble with list view and adapter.
Adapter in getView method reuse "old" item view. And you must setup all content again
I mean: if you use viewHolder.imageViewIconItem.setVisibility(ImageView.INVISIBLE); at one case you must use viewHolder.imageViewIconItem.setVisibility(ImageView.VISIBLE); at second case
here some code which can help you:
if(navDrawerItems.get(position).getHeaderVisibility()) {
viewHolder.textViewTitleItem.setVisibility(TextView.INVISIBLE);
viewHolder.imageViewIconItem.setVisibility(ImageView.INVISIBLE);
viewHolder.textViewHeaderItem.setVisibility(TextView.VISIBLE);
viewHolder.dividerViewItem.setVisibility(View.VISIBLE);
viewHolder.textViewHeaderItem.setText(navDrawerItems.get(position).getHeader());
Log.d("NavDrawerAdapter: ", "3a");
} else {
viewHolder.textViewHeaderItem.setVisibility(TextView.INVISIBLE);
viewHolder.dividerViewItem.setVisibility(View.INVISIBLE);
viewHolder.textViewTitleItem.setVisibility(TextView.VISIBLE);
viewHolder.imageViewIconItem.setVisibility(ImageView.VISIBLE);
viewHolder.imageViewIconItem.setImageResource(navDrawerItems.get(position).getIcon());
viewHolder.textViewTitleItem.setText(navDrawerItems.get(position).getTitle());
Log.d("NavDrawerAdapter: ", "3b");
}
I've found the problem why I wasn't able to achieve what I wanted. I'm leaving it here just for someone who could have the same problem.
When I was setting text and image in the viewHolder, I was just doing it inside if(convertView == null){...}. Instead I took that part after the if(){...}else{...}.
So after else{viewHolder = (ViewHolderItem)convertView.getTag();} I coded another switch(position) and the same cases where I setText() and setImageResource() for my different layout types.
Hope it will be useful for someone.
I'm trying to make 'dynamic' listview that contains 0-2 headers and 0-1 footer(based on the needed mode).
If I use the order
getListView().addFooterView(footerView, null, true);
getListView().setAdapter(myAdapter);
I receive an error:
java.lang.NullPointerException
at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:778)
at android.widget.ListView.addFooterView(ListView.java:364)
at com.my.fragments.QuestionListFragment.updateList(QuestionListFragment.java:63)
and if I switch the lines to
getListView().setAdapter(myAdapter);
getListView().addFooterView(footerView, null, true);
no errors, but footer view doesn't appear on mode change (it appears on the next mode change, so I assume the code is working).
footerView is not null at this moment in the runtime
I can't figure out what is the problem here, but I really need headers and footers to be part of the listview(I can make it with a ScrollView and separate frames, but that won't do)
Update: A thing to add: data which is shown in the list is being loaded asyncronously and is stored in the separate static ArrayList. I use setAdapter(null) on the loading start and setAdapter(myAdapter) on complete to modify the ListView. Maybe the problem is here?
Update2
view_question_list_footer.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_marginTop="2dip" android:layout_marginBottom="2dip">
<TextView android:textAppearance="?android:attr/textAppearanceSmall" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:textStyle="bold" android:text="Load More Questions" android:gravity="center"
android:layout_gravity="center" android:lines="3" android:textColor="#android:color/white"></TextView>
</FrameLayout>
QuestionAdapter.java
public class QuestionAdapter extends BaseAdapter {
public class BrowseSettings {
public SortingMode sortingMode = SortingMode.SORT_BY_DATE;
public boolean isAnswered = true;
public int categoryFilter = -1;
public String textFilter = null;
}
private LayoutInflater inflater = null;
private BrowseSettings settings = new BrowseSettings();
private LoaderListener loaderListener = null;
public QuestionAdapter(Context context, LoaderListener listener) {
inflater = LayoutInflater.from(context);
loaderListener = listener;
}
private void loadData() {
QAData.questions.clear();
appendData();
}
public void appendData() {
new QuestionLoaderThread(settings.isAnswered, settings.sortingMode, settings.categoryFilter, settings.textFilter,
QAData.questions.getCount(), BaseRequest.DEFAULT_COUNT_VALUE, loaderListener).start();
}
public void applyCategoryFilter(int filter) {
settings.categoryFilter = filter;
loadData();
}
public void applyTextFilter(String filter) {
settings.textFilter = filter;
loadData();
}
#Override
public int getCount() {
return QAData.questions.getCount();
}
#Override
public Object getItem(int position) {
return QAData.questions.get(position);
}
#Override
public long getItemId(int position) {
return QAData.questions.get(position).getId();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
QuestionViewHolder viewHolder = null;
if(convertView == null) {
convertView = inflater.inflate(R.layout.view_question, null);
viewHolder = new QuestionViewHolder();
viewHolder.content = (TextView) convertView.findViewById(R.id.QuestionContent);
viewHolder.likes = (TextView) convertView.findViewById(R.id.QuestionLikeCounter);
viewHolder.question = QAData.questions.get(position);
convertView.setTag(viewHolder);
} else {
viewHolder = (QuestionViewHolder) convertView.getTag();
}
viewHolder.content.setText(Html.fromHtml(viewHolder.question.getFormattedQuestion()));
viewHolder.likes.setText(String.valueOf(viewHolder.question.getLikesCount()));
return convertView;
}
private class QuestionViewHolder {
private TextView content;
private TextView likes;
private QAQuestion question;
}
}
Try using getListView().addFooterView(footerView); instead.