I'm trying to make category listview . I want use my code easy to understand and using
I have a MainActivity class
public class MainActivity extends Activity{
private MyCustomAdapter mAdapter;
ListView lst;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lst = (ListView)findViewById(R.id.lstView);
mAdapter = new MyCustomAdapter(this);
for (int i = 1; i < 50; i++) {
mAdapter.addItem("Sameer Blog " + i);
if (i % 4 == 0) {
mAdapter.addSeparatorItem("Ahmad " + i);
}
}
lst.setAdapter(mAdapter);
}
}
and a MyCustomAdapter class like this
public class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<String> mData = new ArrayList<String>();
private LayoutInflater mInflater;
private Context context;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter(Context c) {
this.context = c;
mInflater = (LayoutInflater)context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
public int getCount() {
return mData.size();
}
public String getItem(int position) {
return mData.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
TextView txtView = null;
int type = getItemViewType(position);
if (convertView == null) {
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.list_item, null);
txtView = (TextView)convertView.findViewById(R.id.txtItem);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.list_header, null);
txtView = (TextView)convertView.findViewById(R.id.txtHeader);
break;
}
}
txtView.setText(mData.get(position));
return convertView;
}
}
But I always get NullPointerException in logcat . Somebody can hep me ????
May be it is due to
notifyDataSetChanged();
you call in addItem and addSeparatorItem without setting adapter in listview.
Try changing your:
public MyCustomAdapter(Context c) {
this.context = c;
mInflater = (LayoutInflater)context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
}
to:
public MyCustomAdapter(Context c) {
this.context = c;
mInflater =LayoutInflater.from(getContext());
}
Related
I am trying to create a listview with three different item types I have a code that works with two XML files
Here is the adapter code:
private class MyCustomAdapter extends ArrayAdapter<String> {
String hello;
private String place;
int image;
private String temp;
private String humidity;
private String windspeed;
private String condition;
private int imageTop;
private String time;
private static final int TYPE_WEATHER = 0;
private static final int TYPE_TIME = 1;
private static final int TYPE_TOP = 2;
private static final int TYPE_MAX_COUNT = 3 + 1;
private ArrayList<String> mData = new ArrayList<String>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter(Context context, int resource) {
super(context, resource);
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addWeather(final String place,final int image , final String temp,final String humidity,final String windspeed,final String condition) {
mData.add(place);
this.place = place;
this.image = image;
this.temp = temp;
this.humidity = humidity;
this.windspeed = windspeed;
this.condition = condition;
notifyDataSetChanged();
}
public void addFavapp(final String helloworld){
mData.add(place);
this.hello = helloworld;
notifyDataSetChanged();
}
public void addItem(final String item) {
this.time = item;
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_WEATHER : TYPE_TIME;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_WEATHER:
convertView = mInflater.inflate(R.layout.weather_item, null);
//Handling xml file weather_item
break;
case TYPE_TIME:
convertView = mInflater.inflate(R.layout.time_card_item, null);
holder.textView = (TextView)convertView.findViewById(R.id.two);
holder.textView.setText(time);
break;
case TYPE_TOP:
convertView = mInflater.inflate(R.layout.top_card_item, null);
//Handling xml file top_card_item
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
public ImageView image;
public TextView txtTemp;
public ImageView imageView;
public TextView txthumidity;
public TextView txtWind;
public TextView txtCond;
}
I tried creating a method called "addFavapp" to add my third XML file but I couldn't get it to work.
Help please.
Got it fixed by replacing
return mSeparatorsSet.contains(position) ? TYPE_WEATHER : TYPE_TIME;
Inside the getItemViewType
To
return position;
I have an Adapter class that implements ListView with headers.
//Adapter Class
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private static final int TYPE_GRAY_SEPARATOR = 2;
private TreeSet<Integer> mGraySeparatorsSet = new TreeSet<Integer>();
private ArrayList<ContentWrapper> mData = new ArrayList<ContentWrapper>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter(Context context)
{
mInflater = LayoutInflater.from(context);
}
public void addItem(ContentWrapper value) {
mData.add(value);
notifyDataSetChanged();
}
public void addSeparatorItem(ContentWrapper value) {
mData.add(value);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
public ContentWrapper getItem(int position) {
return mData.get(position);
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
public int getCount() {
return mData.size();
}
public long getItemId(int position) {
Log.v("getItemId Position", ""+position);
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.white, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.black, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
} holder.textView.setText(mData.get(position).getItem());
if (type == TYPE_ITEM) {
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder x = new AlertDialog.Builder(getActivity());
x.setIcon(R.drawable.ic_launcher)
.setTitle(mData.get(position).getItem())
.setMessage(mData.get(position).getItemDescription())
.setCancelable(true)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg,
int arg1) {
}
});
AlertDialog a = x.create();
a.show();
}
return null;
}
});
} else {
holder.textView.setOnClickListener(null);
}
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
In this I truly understand the implementation of getView method (ViewHolder,convertView,etc).
The above code runs smoothy but I do not understand that why we are using the methods
addItem
addSeparatorItem
getItemViewType
getViewTypeCount
getCount
getItemId
Can Anyone explain me the scenario clearly !
Thanks in advance..
These all are the call back methods. You can have the clear definition of these methods in below mentioned link.
http://developer.android.com/reference/android/widget/BaseAdapter.html
Let me give you an example of getItem()
Whenever new listview row is created, adapte willl get item details from this call back method.
Similarly whenever list is created, getCount() is called.
Suppose you have 12 items in listview. But you pass 10 in getCount(). it will show only ten items in list view.
The below code is running the custom listview implemented in a seperate project.
public class MainActivity extends ListActivity implements OnTouchListener{
private MyCustomAdapter mAdapter;
Activity temp = this;
String []s = new String[500];
ArrayList<GS> q = new ArrayList<GS>();
ListView lv;
int count=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DBAdapter db = DBAdapter.getDBAdapter(getApplicationContext());
if (!db.checkDatabase())
{
db.createDatabase(getApplicationContext());
}
db.openDatabase();
q = db.getData();
mAdapter = new MyCustomAdapter();
mAdapter.addSeparatorItem(new ContentWrapper(q.get(0).getA_name(),null));
mAdapter.addItem(new ContentWrapper(q.get(0).getAS_name(), q.get(0).getDesc_art()));
for (int i = 1; i < 460; i++) {
if (!(q.get(i).getA_name().trim().equals(q.get(i-1).getA_name().trim()))) {
mAdapter.addSeparatorItem(new ContentWrapper(q.get(i).getA_name(), null));
}
mAdapter.addItem(new ContentWrapper(q.get(i).getAS_name(), q.get(i).getDesc_art()));
}
setListAdapter(mAdapter);
}
//Adapter Class
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<ContentWrapper> mData = new ArrayList<ContentWrapper>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(ContentWrapper value) {
mData.add(value);
notifyDataSetChanged();
}
public void addSeparatorItem(ContentWrapper value) {
mData.add(value);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
public ContentWrapper getItem(int position) {
return mData.get(position);
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
public int getCount() {
return mData.size();
}
public long getItemId(int position) {
Log.v("getItemId Position", ""+position);
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.activity_main1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.activity_main2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
count++;
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
} holder.textView.setText(mData.get(position).getItem());
if (type == TYPE_ITEM) {
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder x = new AlertDialog.Builder(temp);
Log.v("position",""+position);
x.setIcon(R.drawable.ic_launcher)
// .setTitle(q.get(position-count).getAS_name())
.setTitle(mData.get(position).getItem())
// .setMessage(q.get(position-count).getDesc_art())
.setMessage(mData.get(position).getItemDescription())
.setCancelable(true)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg,
int arg1) {
}
});
AlertDialog a = x.create();
a.show();
}
});
} else {
holder.textView.setOnClickListener(null);
}
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}
Now I want it to be running the same in my App with Fragment.
I just know that using fragment = new ContentsFragment(); initiates it in fragment.
should it be extending ListFragment with a default constructor & an onCreateView(...) which I have inflated the another activities
I am new to fragments & i don't know what things should be changed in the code.
Please help !
EDIT:
I am showing my implemented code of what i have tried & i am getting 4 errors which are have specified in the code:
public class ContentsFragment extends Fragment implements OnTouchListener{
private MyCustomAdapter mAdapter;
Activity temp = this;// error: Type mismatch: cannot convert from ContentsFragment to Activity
String []s = new String[500];
ArrayList<GS> q = new ArrayList<GS>();
ListView lv;
int count=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DBAdapter db = DBAdapter.getDBAdapter(getApplicationContext());//error :The method getApplicationContext() is undefined for the type ContentsFragment
if (!db.checkDatabase())
{
db.createDatabase(getApplicationContext());//error : The method getApplicationContext() is undefined for the type ContentsFragment
}
db.openDatabase();
q = db.getData();
mAdapter = new MyCustomAdapter();
mAdapter.addSeparatorItem(new ContentWrapper(q.get(0).getA_name(),null));
mAdapter.addItem(new ContentWrapper(q.get(0).getAS_name(), q.get(0).getDesc_art()));
for (int i = 1; i < 460; i++) {
if (!(q.get(i).getA_name().trim().equals(q.get(i-1).getA_name().trim()))) {
mAdapter.addSeparatorItem(new ContentWrapper(q.get(i).getA_name(), null));
}
mAdapter.addItem(new ContentWrapper(q.get(i).getAS_name(), q.get(i).getDesc_art()));
}
setListAdapter(mAdapter); //error : The method getApplicationContext() is undefined for the type ContentsFragment
}
//Adapter Class
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<ContentWrapper> mData = new ArrayList<ContentWrapper>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(ContentWrapper value) {
mData.add(value);
notifyDataSetChanged();
}
public void addSeparatorItem(ContentWrapper value) {
mData.add(value);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
public ContentWrapper getItem(int position) {
return mData.get(position);
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
public int getCount() {
return mData.size();
}
public long getItemId(int position) {
Log.v("getItemId Position", ""+position);
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.activity_main1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.activity_main2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
count++;
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
} holder.textView.setText(mData.get(position).getItem());
if (type == TYPE_ITEM) {
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder x = new AlertDialog.Builder(temp);
Log.v("position",""+position);
x.setIcon(R.drawable.ic_launcher)
// .setTitle(q.get(position-count).getAS_name())
.setTitle(mData.get(position).getItem())
// .setMessage(q.get(position-count).getDesc_art())
.setMessage(mData.get(position).getItemDescription())
.setCancelable(true)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg,
int arg1) {
}
});
AlertDialog a = x.create();
a.show();
}
});
} else {
holder.textView.setOnClickListener(null);
}
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}
setListAdapter is a method of ListFragment. So you need to extend ListFragment to use the same.
Change this
mAdapter = new MyCustomAdapter();
to
mAdapter = new MyCustomAdapter(getActivity());
And Then
public MyCustomAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
I'm trying to scroll my simple listview, but unfortunately it's not scrolling smoothly.
I can't figure out what seem to be the problem. I'm not doing anything fancy.
public class ArticleRowAdapter extends BaseAdapter {
private static final int TYPE_MAINARTICLE = 0;
private static final int TYPE_ARTICLE = 1;
private static final int TYPE_MAX_COUNT = TYPE_ARTICLE + 1;
private Context context;
private ArrayList<ArticleRow> mData = new ArrayList<ArticleRow>();
private LayoutInflater mInflater;
public ArticleRowAdapter(Context context,ArrayList<ArticleRow> data) {
this.context = context;
this.mData = data;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
static class ArticleRowHolder
{
TextView tvTitle;
ImageView ivImage;
TextView tvSubTitle;
}
public void addItem(final ArticleRow item) {
mData.add(item);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return position == 0 ? TYPE_MAINARTICLE : TYPE_ARTICLE;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public ArticleRow getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ArticleRowHolder holder = null;
int type = getItemViewType(position);
if(convertView == null)
{
holder = new ArticleRowHolder();
switch(type)
{
case TYPE_MAINARTICLE:
convertView = mInflater.inflate(R.layout.mainarticle,parent, false);
break;
case TYPE_ARTICLE:
convertView = mInflater.inflate(R.layout.article,parent , false);
break;
}
holder.tvTitle = (TextView)convertView.findViewById(R.id.articleTitle);
holder.ivImage = (ImageView)convertView.findViewById(R.id.articleImage);
holder.tvSubTitle = (TextView)convertView.findViewById(R.id.articleSubTitle);
convertView.setTag(holder);
}
else
{
holder = (ArticleRowHolder)convertView.getTag();
}
ArticleRow articleRow = mData.get(position);
holder.tvTitle.setText((CharSequence)articleRow.title);
holder.tvSubTitle.setText(Html.fromHtml(articleRow.subTitle));
if(articleRow.imageURL == null)
holder.ivImage.setImageDrawable(this.context.getResources().getDrawable(R.drawable.dunk));
else
{
holder.ivImage.setImageDrawable(this.context.getResources().getDrawable(R.drawable.dunk));
}
return convertView;
}
I can say that the reason of lags are imageViews, thats for sure:
holder.ivImage = (ImageView)convertView.findViewById(R.id.articleImage);
try to not to fill imageViews with images and see what happens :). Also check google's BitmapFun and LazyList - both about images in list/grid views
I have array list, I used it in adapter class. All things worked good but when I delete specific index from the array list(in my case data) the size of array list equal zero.
Here is my Adapter class
public class MainLocalListAdapter extends BaseAdapter{
public static final int LIMIT_LIST_COUNT = 20;
private Activity activity;
private static ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
private int count = LIMIT_LIST_COUNT;
private int customPosition = 0;
public MainLocalListAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data = d;
if(count > data.size()) count = data.size();
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return count;//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) {
ViewHolder holder = null;
if(convertView==null){
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.playlist_local_item, null);
holder.textView = (TextView)convertView.findViewById(R.id.waveTitle2); // title
holder.textView.setTypeface(UtiliShare.getTf());
holder.btnCancel = (ImageView) convertView.findViewById(R.id.btndel);
holder.btnCancel.setOnClickListener(mOnClickListener);
convertView.setTag(holder);
}else{
holder = (ViewHolder)convertView.getTag();
}
if(!data.isEmpty()) {
HashMap<String, String> song = data.get(position);
holder.btnCancel.setTag(position);
holder.textView.setText(song.get(UtiliShare.KEY_TITLE));
}
return convertView;
}
private static class ViewHolder{
TextView textView;
ImageView btnCancel;
}
private OnClickListener mOnClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainLocalListAdapter.this.activity, ""+v.getTag(), Toast.LENGTH_SHORT).show();
data.remove((Integer) v.getTag());
// Here data.size = 0 ????????????
int nval = data.size();
Log.d("list", ""+nval);
notifyDataSetChanged();
}
};
public int getCustomPosition() {
return customPosition;
}
public void setCustomPosition(int cPosition) {
customPosition = cPosition;
int nval = (data.size() - customPosition);
if(nval < LIMIT_LIST_COUNT) this.count = nval;
else count = LIMIT_LIST_COUNT;
}
}
I don't have error because I check data size before get data from it in getView().
How can I fix this??