I used to create a custom adapter which is based upon BaseAdapter class, not ArrayAdapter.
But here is an issue, when I try to populate my adapter with new data(whatever it is), my AdapterView represents more items, than it supposed to have.
Suppose we have an Activity, ListFragment and custom Adapter.
Implementation of an Adapter:
public class ContactAdapter extends BaseAdapter {
private List<Entry<String,String>> mDataModel;
private LayoutInflater mInflater;
private boolean[] isChecked;
private int mResourceId;
private static class ViewHolder {
private TextView adapterText;
private TextView adapterDate;
}
public ContactAdapter(Context context,int mResourceId) {
this(context, mResourceId,new ArrayList<Entry<String,String>>());
}
public ContactAdapter(Context context, int mResourceId,List<Entry<String,String>> mDataModel) {
this.mInflater = LayoutInflater.from(context);
this.mResourceId = mResourceId;
this.mDataModel = mDataModel;
this.isChecked = new boolean[mDataModel.size()];
}
#Override
public int getCount() {
return mDataModel.size();
}
#Override
public Entry<String,String> getItem(int position) {
return mDataModel.get(position);
}
public void selectItem(int position) {
isChecked[position] = !isChecked[position];
}
public void add(final Entry<String,String> entry) {
mDataModel.add(entry);
if(mDataModel.size()>isChecked.length) {
isChecked = Arrays.copyOf(isChecked, isChecked.length / 2 +
mDataModel.size());
}
notifyDataSetChanged();
}
public void unCheckItems() {
for (int index = 0; index < mDataModel.size(); index++)
isChecked[index] = false;
}
public void removeItem() {
for(int index=0;index<mDataModel.size();index++) {
if (isChecked[index])
mDataModel.remove(index);
}
notifyDataSetChanged();
}
#Override
public long getItemId(int position) {
return mDataModel.get(position).hashCode();
}
#Override
public View getView(int position,View convertView, ViewGroup parentGroup) {
ViewHolder holder;
if(convertView==null) {
convertView=mInflater.inflate(mResourceId,parentGroup,false);
holder=new ViewHolder();
holder.adapterDate=(TextView)(convertView.findViewById(R.id.adapterDate));
holder.adapterText=(TextView)(convertView.findViewById(R.id.adapterText));
convertView.setTag(holder);
}
else
holder=(ViewHolder)(convertView.getTag());
holder.adapterDate.setText(mDataModel.get(position).getValue());
holder.adapterText.setText(mDataModel.get(position).getKey());
convertView.setSelected(isChecked[position]);
return convertView;
}
}
Also I have a usual ListFragment's implementation with additional method addTo(...), in order to add rows to ListView.Data comes from an Activity.
Here is the method, which I call within an Activity to send a data to ListFragment:
public void addToContact(View view) {
String contact = mContact.getText().toString();
if(!contact.isEmpty()) {
if (contactFragment == null) {
contactFragment = (ContactFragment) getSupportFragmentManager().findFragmentByTag(BundleKey.CONTACT_FRAGMENT);
}
Calendar calendar = Calendar.getInstance();
final Entry<String, String> entry = new Entry<>(contact,
calendar.get(Calendar.MONTH) + "/" + calendar.get(Calendar.DAY_OF_MONTH) + "/"
+ calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE));
contactFragment.addEntry(entry);
}
mContact.getText().clear();
Toast.makeText(this,(contact.isEmpty()?
"Enter contact":"Contact has been added"),Toast.LENGTH_LONG).show();
}
So, when I add any new item, my ListView shows two similar items instead of one.Do you know how to fix it?
Related
Im new in realm db. I completed add and get data in realm db. But, I couldn't sort(ascending and descending).Im my code it display items in listview. Listview contains 5 list and each list contains 4 field(name, age, skill and date). if I sort(ascending) name, need to ascending in 5 list.My code is not work
I post my code here,
private void Ascending_order() {
realm.beginTransaction();
RealmResults<Employee> result = realm.where(Employee.class)
.sort("name", Sort.ASCENDING).findAll();
realm.copyFromRealm(result);
realm.commitTransaction();
employeedetailadapter.notifyDataSetChanged();
}
Adapter class:
public class EmployeeDetailAdapter extends BaseAdapter {
private ArrayList<Employee>employeeDetaillists = new ArrayList<>();
private Context c;
private LayoutInflater inflater;
private OnItemClick mCallback;
private SimpleDateFormat df = new SimpleDateFormat("dd/mm/yyyy");
public EmployeeDetailAdapter(Context c,ArrayList<Employee> employeeDetaillists, OnItemClick listener) {
this.employeeDetaillists = employeeDetaillists;
this.c= c;
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.mCallback = listener;
}
#Override
public int getCount() {
return employeeDetaillists.size();
}
#Override
public Object getItem(int position) {
return employeeDetaillists.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
Holder holder;
if (v==null){
v= (View) inflater.inflate(R.layout.list_single_item,null);
holder = new Holder();
holder.tvPersonName = (TextView) v.findViewById(R.id.tvPersonName);
holder.tvPersonAge = (TextView) v.findViewById(R.id.tvPersonAge);
holder.tvPersonSkill = (TextView) v.findViewById(R.id.tvPersonSkill);
holder.ivEditPesonDetail=(ImageView)v.findViewById(R.id.ivEditPesonDetail);
holder.tvPersondate=(TextView)v.findViewById(R.id.tvPersondate);
holder.ivDeletePerson=(ImageView)v.findViewById(R.id.ivDeletePerson);
v.setTag(holder);
}else{
holder = (Holder) v.getTag();
}
holder.tvPersonName.setText(employeeDetaillists.get(position).getName());
holder.tvPersonAge.setText(employeeDetaillists.get(position).getAge());
holder.tvPersonSkill.setText(employeeDetaillists.get(position).getSkill());
String strDate = df.format(employeeDetaillists.get(position).getSdate());
holder.tvPersondate.setText(strDate);
holder.ivDeletePerson.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Delete(employeeDetaillists.get(position).getName(),position);
}
});
return v;
}
private void Delete(String name, int position) {
mCallback.onClickdelete(name, position);
}
public void updateData(RealmResults<Employee> result) {
}
class Holder {
TextView tvPersonName, tvPersonAge, tvPersonSkill,tvPersondate;
ImageView ivDeletePerson, ivEditPesonDetail;
}
}
Your code does't change db. You just get sorted items but don't use them.
realm.copyFromRealm(result); // this line does nothing
realm.commitTransaction(); // this one too, because you change nothing
employeedetailadapter.notifyDataSetChanged(); // you data is the same, so this line also useless here
To see your data sorted you should use RealmResults in your adapter. With this approach your list always will sorted, even after adding new items. But note: your adapter should extends RealmRecyclerViewAdapter.
You should run this code before creating adapter and use result inside adapter:
RealmResults<Employee> result = realm.where(Employee.class)
.sort("name", Sort.ASCENDING).findAll();
Also you can try manually update data of your adapter.
private void Ascending_order() {
RealmResults<Employee> result = realm.where(Employee.class)
.sort("name", Sort.ASCENDING).findAll();
employeedetailadapter.updateData(result); // update data inside adapter before calling `notifyDataSetChanged`
employeedetailadapter.notifyDataSetChanged();
}
You need to create updateData method yourself:
public void updateData(RealmResults<Employee> result) {
employeeDetaillists = new ArrayList<Employee>(result);
}
First of all, while getting data from Realm you don't need to write it in Transaction. Write Transaction is required only when you are adding data in realm or updating any realm object.
And about your problem, To get sorted data from realm, You can do it like this
RealmResults<Employee> result = realm.where(Employee.class).sort("name", Sort.ASCENDING).findAll();
Now the data you got is sorted, If you still see wrong order in your ListView then there could be some issue in your Adapter. If you share your adapter code, then I can help further :)
Updated:
Adapter Class
public class EmployeeDetailAdapter extends BaseAdapter {
private RealmResults<Employee> employeeDetaillists;
private Context c;
private LayoutInflater inflater;
private OnItemClick mCallback;
private SimpleDateFormat df = new SimpleDateFormat("dd/mm/yyyy");
public EmployeeDetailAdapter(Context c,RealmResults<Employee> employeeDetaillists, OnItemClick listener) {
this.employeeDetaillists = employeeDetaillists;
this.c= c;
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.mCallback = listener;
}
#Override
public int getCount() {
return employeeDetaillists.size();
}
#Override
public Object getItem(int position) {
return employeeDetaillists.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
Holder holder;
if (v==null){
v= (View) inflater.inflate(R.layout.list_single_item,null);
holder = new Holder();
holder.tvPersonName = (TextView) v.findViewById(R.id.tvPersonName);
holder.tvPersonAge = (TextView) v.findViewById(R.id.tvPersonAge);
holder.tvPersonSkill = (TextView) v.findViewById(R.id.tvPersonSkill);
holder.ivEditPesonDetail=(ImageView)v.findViewById(R.id.ivEditPesonDetail);
holder.tvPersondate=(TextView)v.findViewById(R.id.tvPersondate);
holder.ivDeletePerson=(ImageView)v.findViewById(R.id.ivDeletePerson);
v.setTag(holder);
}else{
holder = (Holder) v.getTag();
}
holder.tvPersonName.setText(employeeDetaillists.get(position).getName());
holder.tvPersonAge.setText(employeeDetaillists.get(position).getAge());
holder.tvPersonSkill.setText(employeeDetaillists.get(position).getSkill());
String strDate = df.format(employeeDetaillists.get(position).getSdate());
holder.tvPersondate.setText(strDate);
holder.ivDeletePerson.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Delete(employeeDetaillists.get(position).getName(),position);
}
});
return v;
}
private void Delete(String name, int position) {
mCallback.onClickdelete(name, position);
}
public void updateData(RealmResults<Employee> result) {
}
class Holder {
TextView tvPersonName, tvPersonAge, tvPersonSkill,tvPersondate;
ImageView ivDeletePerson, ivEditPesonDetail;
}
}
In your Activity please change following function
private void Ascending_order() {
result = realm.where(Employee.class)
.sort("name", Sort.ASCENDING).findAll();
employeedetailadapter.notifyDataSetChanged();
}
"result" list should be declared on class level and should be passed to Adapter's constructor as well.
Like
class Activity {
RealmResults<Employee> result;
EmployeeDetailAdapter employeedetailadapter;
//// Other Code
public onCreate(Bundle b) {
result = realm.where(Employee.class).findAll();
employeedetailadapter = new EmployeeDetailAdapter(this, result, listener);
// Other code
}
}
hi i want to get values from database and show in listview
i get 6 value from database and send it to adapter but all 6 row is last item to send to adapter
when i add
ViewHolder holder;
android studio after alt + enter change to
RecyclerView.ViewHolder holder;
i read this post's but can not fix problem
Rows being repeated in ListView
Duplicated entries in ListView
Android Listview row repeating item
List item repeating in android customized listview
I know this question is duplicate but can not fix it
Thanks in advance
my adapter :
public class lim_sms_adapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<lim_sms> lim_smsItems;
public lim_sms_adapter (Activity activity, List<lim_sms> lim_smsItems) {
this.activity = activity;
this.lim_smsItems = lim_smsItems;
}
#Override
public int getCount() {
return lim_smsItems.size();
}
#Override
public Object getItem(int location) {
return lim_smsItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
#SuppressLint("SetTextI18n")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.row_lim_sms, null);
TextView number = (TextView) convertView.findViewById(R.id.row_lim_sms_txt_number);
lim_sms m = lim_smsItems.get(position);
number.setText(m.getSms_number());
return convertView;
}
}
my class seter and geter :
public class lim_sms {
String sms_number;
public lim_sms(String sms_number) {
this.sms_number = sms_number;
}
public lim_sms() {
}
public String getSms_number() {
return sms_number;
}
public void setSms_number(String sms_number) {
this.sms_number = sms_number;
}
}
my activity :
public class list_limit_sms extends AppCompatActivity {
private List<lim_sms> limit_sms = new ArrayList<lim_sms>();
private lim_sms_adapter adapter;
private sms_database sms_db = new sms_database(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_limit_sms);
ListView listView = (ListView) findViewById(R.id.list_lim_sms);
adapter = new lim_sms_adapter(this, limit_sms);
listView.setAdapter(adapter);
lim_sms cy = new lim_sms();
List<sms_class> sms_list = sms_db.getAllContacts();
for (sms_class ss : sms_list) {
//String log = "Id: "+ss.getId()+" ,num: " + ss.getNum() + " ,type: " + ss.getType();
//Toast.makeText(this, ""+log, Toast.LENGTH_LONG).show();
cy.setSms_number(ss.getNum());
Toast.makeText(this, ""+ss.getNum(), Toast.LENGTH_SHORT).show();
limit_sms.add(cy);
adapter.notifyDataSetChanged();
}
}
}
I have created a class PickedDropsAdapter that extends ArrayAdapter for a listView that lists Objects from a List
Adding and removing basically works fine except that position in getView is always 0 and I just can't figure out, why.
I found a few similar question but none of the answers was really helping
Maybe important to mention is that listView is in a Fragment which again is in a ViewPager with two pages.
PickedDropsAdapter.java
public class PickedDropsAdapter extends ArrayAdapter {
private LayoutInflater myInflater;
private List<PickedDrop> pickedList;
public PickedDropsAdapter(Context context, int resource, List objects){
super(context, resource, objects);
myInflater = LayoutInflater.from(context);
setData(objects);
}
public void setData(List list){
this.pickedList = list;
}
#Override
public int getPosition(Object item) {
return super.getPosition(item);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView profileName;
if (convertView == null) {
convertView = myInflater.inflate(R.layout.picked_drop, null);
profileName = (TextView)convertView.findViewById(R.id.profileName);
Log.i("TAG", "Name in adapter: " + pickedList.get(position).name);
Log.i("TAG", "Postion in adapter: " + position);
profileName.setText(pickedList.get(position).name);
pickedList.get(position).makeActive(convertView);
}
return convertView;
}
}
PickedDrop
public class PickedDrop extends Fragment {
int id, listLoc;
String name;
RelativeLayout pickedLayout;
PickedDropsFrag parentFrag = null;
public static PickedDrop newInstance(String nameParam, int idParam) {
final PickedDrop fragment = new PickedDrop();
fragment.name = nameParam;
Log.i("TAG", "Drop name: " + fragment.name);
fragment.id = idParam;
return fragment;
}
public PickedDrop() {
// Required empty public constructor
}
public void openDrop(){
MainActivity mainActivity = (MainActivity)parentFrag.getActivity();
mainActivity.openDrop(this);
}
public void openDrop(int i){
listLoc = i;
MainActivity mainActivity = (MainActivity)parentFrag.getActivity();
mainActivity.openDrop(this);
}
public void makeActive(View convertView){
pickedLayout = (RelativeLayout)convertView.findViewById(R.id.pickedLayout);
}
}
Part of PickedDropsFrag (The fragment that contains the listView)
public class PickedDropsFrag extends Fragment {
private OnFragmentInteractionListener mListener;
PickedDropsAdapter pickedAdapter;
ListView pickedListView;
List<PickedDrop> pickedList;
public PickedDropsFrag() {
// Required empty public constructor
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
pickedListView = (ListView)getView().findViewById(R.id.pickedListView);
pickedListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
PickedDrop drop = (PickedDrop) adapterView.getItemAtPosition(i);
drop.openDrop(i);
}
});
pickedList = new ArrayList<>();
pickedAdapter = new PickedDropsAdapter(
getActivity(),
R.layout.picked_drop,
pickedList
);
pickedListView.setAdapter(pickedAdapter);
}
public void addToPicked(PickedDrop drop){
drop.parentFrag = this;
//pickedList.add(drop);
pickedAdapter.add(drop);
drop.listLoc = pickedList.size() - 1;
//pickedAdapter.notifyDataSetChanged();
drop.openDrop();
}
That should be everything important, I hope I didn't forget anything.
Update following methods in your Adapter:
public class PickedDropsAdapter extends ArrayAdapter {
#Override
public int getCount() {
return pickedList.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView profileName;
if (convertView == null) {
convertView = myInflater.inflate(R.layout.picked_drop, null);
}
profileName = (TextView)convertView.findViewById(R.id.profileName);
Log.i("TAG", "Name in adapter: " + pickedList.get(position).name);
Log.i("TAG", "Postion in adapter: " + position);
profileName.setText(pickedList.get(position).name);
pickedList.get(position).makeActive(convertView);
return convertView;
}
}
I have a TextView outside ListView and i need to add prices when the plus button (ie,quantity is incremented )in ListView is clicked.In my program i am not able to add prices when new position ListView button is clicked.I need to find the total price to be payed by the customer when plus button is clicked in ListView
public class ListAdapter1 extends BaseAdapter {
public int qty=1;
public ArrayList<Integer> quantity = new ArrayList<Integer>();
private TextView total;
private String[] listViewItems,prices,weight;
TypedArray images;
public static int pValue;
private Context context;
public static boolean t=false;
CustomButtonListener customButtonListener;
public void setTextView(TextView total)
{
this.total = total;
}
public ListAdapter1(Context context, String[] listViewItems, TypedArray images, String[] weight, String[] prices) {
this.context = context;
this.listViewItems = listViewItems;
this.images = images;
this.prices=prices;
this.weight=weight;
}
public void setCustomButtonListener(CustomButtonListener customButtonListner)
{
this.customButtonListener = customButtonListner;
}
#Override
public int getCount() {
return 5;
}
#Override
public String getItem(int position) {
return listViewItems[position];
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View row;
final ListViewHolder listViewHolder;
if(convertView == null)
{
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.product,parent,false);
listViewHolder = new ListViewHolder();
listViewHolder.tvProductName = (TextView) row.findViewById(R.id.tvProductName)
listViewHolder.tvPrices = (TextView) row.findViewById(R.id.tvProductPrice);
listViewHolder.btnPlus = (ImageButton) row.findViewById(R.id.ib_addnew);
listViewHolder.edTextQuantity = (EditText) row.findViewById(R.id.editTextQuantity);
listViewHolder.btnMinus = (ImageButton) row.findViewById(R.id.ib_remove);
row.setTag(listViewHolder);
}
else
{
row=convertView;
listViewHolder= (ListViewHolder) row.getTag();
}
try{
listViewHolder.edTextQuantity.setText(quantity.get(position) );
}catch(Exception e){
e.printStackTrace();
}
listViewHolder.btnMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, " " + position, Toast.LENGTH_SHORT).show();
int mValue = Integer.parseInt(listViewHolder.edTextQuantity.getText().toString());
if (mValue <=0) {
System.out.println("not valid");
mValue=0;
listViewHolder.edTextQuantity.setText("" +mValue);
}
else{
pValue=pValue/mValue;
mValue--;
pValue=pValue*mValue;
total.setText(String.valueOf(pValue));
System.out.println("mvalue after reducing-----------"+mValue);
System.out.println("pvalue-----------"+pValue);
listViewHolder.edTextQuantity.setText( "" +mValue );
}
}
});
listViewHolder.btnPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, " " + position, Toast.LENGTH_SHORT).show();
int mValue = Integer.parseInt(listViewHolder.edTextQuantity.getText().toString());
pValue=Integer.parseInt(listViewHolder.tvPrices.getText().toString());
mValue++;
listViewHolder.edTextQuantity.setText("" + mValue);
System.out.println("mValue after increment---" + mValue);
pValue=pValue*mValue;
System.out.println("pvalue-----------"+pValue);
total.setText(String.valueOf(pValue));
}
});
return row;
}
I need to get total price when any of the ListView button is clicked.
First you need to store value in HashMap<> when user click the plus and minus button.
Then sum the all values in HashMap.
For Example
try{
int sum = 0;
for(HashMap<String, String> map : arrayList) {
sum += Integer.parseInt(map.get("mark"));
}
} catch (Exception e) {
//Manage your exception
}
// sum has the value for the marks total.
System.out.println("Total Marks: "+sum);
Refere my previous answer Here
For that you need to create interface which notify in activity where you want that count.
put snippet in adapter to initialize interface and setter.
public interface IEvent {
void onItemChange(int count);
}
private IEvent iEvent;
//setter method for interface
public void setQuanityEvent(IEvent ievent) {
this.lastPageHandler = handler;
}
put this code in btnMinus.setOnClickListener
//if ievent interface variable register via set
if (ievent != null) {
//pValue is quality COUNT you want to send outside listview.
ievent.onItemChange(pValue);
}
activity code after creating adapter instance
//ListAdapter1 adapter = new ListAdapter1(your params);
adapter.setQuanityEvent(new ListAdapter1.IEvent() {
#Override
public void onItemChange(int count) {
}
}
});
I have a very strange problem while using my ListView.
Only a part of my adapter items are renderd in the listview on screen but when I interact with the listview (ie tries to scroll it) all items are renderd properly.
This fenonemon only occurs if i have less items than the screen can show. Take a look at these screenshots below.
Before interaction:
After interaction:
Source code of activity where adding items:
String[] jRests = getResources().getStringArray(R.array.j_restaurants);
String[] lRests = getResources().getStringArray(R.array.l_restaurants);
items = new ArrayList<Object>();
items.add(getString(R.string.campus_j));
for(String item : jRests){
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
}
items.add(getString(R.string.campus_l));
for(String item : lRests){
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
adapter = new BaseSectionAdapter(this, R.layout.list_item_fragment_header);
if(!isTabletView()){
adapter.setSelectedItem(-1);
}
adapter.setItems(items);
Code of adapter:
public class BaseSectionAdapter extends AmazingAdapter {
private LayoutInflater inflater;
private int selectedItem = 0;
private List<Object> items;
private List<SectionItem> sections = new ArrayList<SectionItem>(10);
private List<Class> itemTypes = new ArrayList<Class>();
private List<Integer> sectionPositions = new ArrayList<Integer>();
private int listHeaderLayoutId;
private View headerView;
public static interface ISectionListItem {
public void setProps(View convertView, int position, int selectedItem);
public View getLayout(LayoutInflater inflater);
}
private class SectionItem implements Serializable {
private static final long serialVersionUID = -8930010937740160935L;
String text;
int position;
public SectionItem(String text, int position) {
this.text = text;
this.position = position;
}
}
public BaseSectionAdapter(Context context, int listHeaderLayoutId) {
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
}
public BaseSectionAdapter(Context context, int listHeaderLayoutId, List<Object> listItems) {
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
initListItems(listItems);
}
private void init(Context context) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setSelectedItem(int position) {
selectedItem = position;
}
// public List<ListItem> getItems() {
// return items;
// }
private void initListItems(List<Object> itemList) {
int curSection = -1;
//int curPosition = 0;
//curSection = 0;
this.items = itemList;
itemTypes.clear();
sections.clear();
sectionPositions.clear();
int listSize = itemList.size();
for(int i = 0; i < listSize; i++){
Object currentItem = items.get(i);
if(currentItem instanceof String){
sections.add(new SectionItem((String) currentItem,i));
curSection++;
}
if(!itemTypes.contains(currentItem.getClass())){
itemTypes.add(currentItem.getClass());
}
sectionPositions.add(curSection);
}
Log.d("test", "No of items = "+items.size());
Log.d("test", "No of itemtypes = "+itemTypes.size());
Log.d("test", "View type count = "+getViewTypeCount());
}
public void setItems(List<Object> itemList) {
initListItems(itemList);
}
public int getCount() {
return items==null?0:items.size();
}
#Override
public int getViewTypeCount(){
return (itemTypes.size() == 0)?1:itemTypes.size();
}
#Override
public int getItemViewType(int position){
return itemTypes.indexOf(items.get(position).getClass());
}
#Override
public boolean isEnabled(int position){
return !(items.get(position) instanceof String || items.get(position) instanceof EmptySectionListItem);
}
#Override
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
#Override
protected void onNextPageRequested(int page) {
// TODO Auto-generated method stub
}
#Override
protected void bindSectionHeader(View view, int position,
boolean displaySectionHeader) {
// TextView lSectionTitle = (TextView) view
// .findViewById(R.id.txt_list_header);
// if (displaySectionHeader) {
// lSectionTitle.setVisibility(View.VISIBLE);
// lSectionTitle
// .setText(getSections()[getSectionForPosition(position)]);
// } else {
// lSectionTitle.setVisibility(View.GONE);
// }
}
#Override
public View getAmazingView(int position, View convertView, ViewGroup parent) {
Object curItemObject = items.get(position);
boolean isHeader = (curItemObject instanceof String);
if(convertView == null){
if(isHeader && headerView != null){
convertView = headerView;
}else if(isHeader){
convertView = inflater.inflate(listHeaderLayoutId, null);
headerView = convertView;
}else{
convertView = ((ISectionListItem) curItemObject).getLayout(inflater);
}
}
if(isHeader){
TextView header = ((TextView)convertView.findViewById(R.id.txt_list_header));
header.setText((String)curItemObject);
}else{
((ISectionListItem)curItemObject).setProps(convertView, position, selectedItem);
}
return convertView;
}
#Override
public void configurePinnedHeader(View header, int position, int alpha) {
TextView textView = ((TextView)header.findViewById(R.id.txt_list_header));
textView.setText(getSections()[getSectionForPosition(position)]);
}
#Override
public int getPositionForSection(int section) {
if(section >= sections.size()){
return 0;
}
return sections.get(section).position;
}
#Override
public int getSectionForPosition(int position) {
return sectionPositions.get(position);
}
#Override
public String[] getSections() {
String[] res = new String[sections.size()];
for (int i = 0; i < res.length; i++) {
res[i] = sections.get(i).text;
}
return res;
}
}
Code of layout:
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
FrameLayout listLayout = new FrameLayout(this);
LinearLayout.LayoutParams listParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
listParams.weight = 1;
listLayout.setId(LIST_FRAGMENT_VIEW_ID);
FrameLayout detailLayout = new FrameLayout(this);
LinearLayout.LayoutParams detailParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
detailParams.weight = 2;
detailLayout.setId(DETAIL_FRAGMENT_VIEW_ID);
layout.addView(listLayout, listParams);
layout.addView(detailLayout, detailParams);
if(savedInstanceState == null){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(listLayout.getId(), (Fragment) listFragment, TWO_PANEL_LIST_FRAGMENT_TAG);
ft.add(detailLayout.getId(), detailFragment);
ft.commit();
}
setContentView(layout);
try calling notifyDataSetChanged() in runOnUIThread() method like I have shown below and it will work like a charm. :)
runOnUiThread(new Runnable() {
#Override
public void run() {
messageAdapter.notifyDataSetChanged();
}
});
i dont know what causes the problem, but if you don't find a logical solution to it you could try something like this:
trigger an onTouchEvent() programmatically whenever you launch the ListView.
scroll down and back up programmatically as soon as the ListView is launched.
etc..
Add ListView widget to layout.xml and add content of list to that. Do not use FrameLayout as it probably is the cause of the problem. It is updating content after touch so the Layout it is on is no implementing the correct onCreate() setup as the ListView widget has.
Are you calling the method notifyDataSetChanged() on your adapter after adding new items? This causes the listview to refresh its view when the underlying dataset is changed.
If it still doesn't work, try notifyDataSetInvalidated() that causes the listview to redraw completely.
Solved it!!!
Problem was with the adapter trying to reuse the same section item. Not good!!!
Changed it to inflate the section item each time we hit a section!