Implementing FloatingGroupExpandableListView in a listview consisting 2 types of headers
Asked Answered
I

2

1

I tried to implement FloatingGroupExpandableListView but I was unable to modify it according to my custom listview.

The below code implements 2 types of headers in the list.

Well, Implementing 2 types of header was a complex task for me & now within that implementing FloatingGroupExpandableListView is not an easy task and I am not able to customize their code according to my custom listview.

Please see MyCustomAdapter class, & please tell me how can I modify it to achieve my task ?

public class ContentsFragment extends ListFragment  implements OnTouchListener {

private MyCustomAdapter mAdapter;
Activity temp = getActivity();

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(getActivity());

if (!db.checkDatabase())   
    db.createDatabase(getActivity());

db.openDatabase();

q = db.getData();

mAdapter = new MyCustomAdapter(getActivity());

mAdapter.addSeparatorItem(new ContentWrapper(q.get(0).getA_name(),null,null));//1st type of seperator
mAdapter.addItem(new ContentWrapper(q.get(0).getAS_name(), q.get(0).getDesc_art(),null));


for (int i = 1; i <= 14; 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,null));//2nd type of separator
}
if(!(q.get(i).getExtra()==null))
  mAdapter.addGraySeparatorItem(new ContentWrapper(q.get(i).getExtra(),null,null));

mAdapter.addItem(new ContentWrapper(q.get(i).getAS_name(), q.get(i).getDesc_art(),null));
}

for (int i = 15; i < 236; 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,null));

  }
  if(!(q.get(i).getExtra()==null))
      mAdapter.addGraySeparatorItem(new ContentWrapper(q.get(i).getExtra(),null,null));


  mAdapter.addItem(new ContentWrapper(q.get(i).getAS_name(), q.get(i).getDesc_art(),null));

    }
//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_GRAY_SEPARATOR = 2;
private static final int TYPE_MAX_COUNT = TYPE_GRAY_SEPARATOR + 1;

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 void addGraySeparatorItem(ContentWrapper value) {
    mData.add(value);
    // save separator position
    mGraySeparatorsSet.add(mData.size() - 1);
    notifyDataSetChanged();
}   


public ContentWrapper getItem(int position) {
    return mData.get(position);
}
@Override
public int getItemViewType(int position) {
    int viewType = TYPE_ITEM;
    if(mSeparatorsSet.contains(position))
       viewType = TYPE_SEPARATOR;
    else if(mGraySeparatorsSet.contains(position)) {
       viewType = TYPE_GRAY_SEPARATOR; 
    }

    return viewType;
    // 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;
        case 2:
            convertView = mInflater.inflate(R.layout.gray, null);
            holder.textView = (TextView)convertView.findViewById(R.id.textViewGray);
            break;

        }
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder)convertView.getTag();
    } holder.textView.setText(mData.get(position).getItem());

    getListView().setFastScrollEnabled(true);
    if (type == TYPE_ITEM) {
        holder.textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { // for printing details in alert dialog
                            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                    builder.setIcon(R.drawable.ic_launcher);
                    final String title = mData.get(position).getItem();
                    builder.setTitle(title);
                    builder.setMessage(mData.get(position).getItemDescription());
                    builder.setCancelable(false);
                    builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
                    AlertDialog alertDialog = builder.create();
                    alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
                        @Override
                        public void onShow(DialogInterface dialog) {
                            AlertDialog alertDialog = (AlertDialog) dialog;
                            ViewGroup viewGroup = (ViewGroup) alertDialog.getWindow()
                                    .getDecorView();
                            TextView textView = findTextViewWithTitle(viewGroup, title);
                            if (textView != null) {
                                textView.setEllipsize(null);
                                textView.setMaxHeight((int) (100 * alertDialog.getContext().getResources().getDisplayMetrics().density)); 
                                textView.setMovementMethod(new ScrollingMovementMethod());
                            }
                        }
                    });
                    alertDialog.show();
                }

                    //Customised Alert dialog 
                private TextView findTextViewWithTitle(ViewGroup viewGroup, String title) {
                    for (int i = 0, N = viewGroup.getChildCount(); i < N; i++) {
                        View child = viewGroup.getChildAt(i);
                        if (child instanceof TextView) {
                            TextView textView = (TextView) child;
                            if (textView.getText().equals(title)) {
                                return textView;
                            }
                        } else if (child instanceof ViewGroup) {
                            ViewGroup vGroup = (ViewGroup) child;
                            return findTextViewWithTitle(vGroup, title);
                        }
                    }
                    return null;
                }


            });
    }else if(type == 1) {
        holder.textView.setOnClickListener(null);
    }
    else
    {
        holder.textView.setOnClickListener(null);
    }

return convertView;
}
}
public static class ViewHolder {
public TextView textView;
public TextView header;
 int previousTop = 0;
}

public boolean onTouch(View v, MotionEvent event) {
return false;
}
}
}

enter image description here

As you can see there are 2 types of headers(1 of black color & 1 of gray color) wit child of white color.

Black background, Gray Background & white background all sh'd be the child view of the green background(it is floatingGroupExpandableHeader)(relative layout id sample_activity_list_group_item_background)! Views from 1-30 are of part 1 , so green background text is part 1 (floatingGroupExpandableHeader) with childs from 1 to 30 irrespective of the fact weather it is Black Background, Gray Background, or white background ! Then at view 31 I want to add another floatingGroupExpandableHeader with text as part 2 (child views from 31-60), I hope what I am trying to achieve is clear !

For FloatingGroupExpandableListView my xml files are ready,I don't want to add any header or footer,

sample_activity_list_group_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >



<RelativeLayout
    android:id="@+id/sample_activity_list_group_item_background"
    android:layout_width="0dp"
    android:layout_height="40dp"
    android:layout_gravity="center_vertical"
    android:layout_weight="1"
    android:background="#FFA2C955"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/sample_activity_list_group_item_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:textColor="#FFFFFFFF"
        android:textSize="20sp" />

    <ImageView
        android:id="@+id/sample_activity_list_group_expanded_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="20dp" />
</RelativeLayout>

</LinearLayout>

sample_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFEDEDED"
android:orientation="vertical" >

<com.diegocarloslima.fgelv.lib.FloatingGroupExpandableListView
    android:id="@+id/sample_activity_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:cacheColorHint="@android:color/transparent"
    android:childDivider="#FF000000"
    android:divider="#FF000000"
    android:dividerHeight="1dp"
    android:paddingLeft="10dp"
    android:paddingTop="10dp" />

</LinearLayout>

Now What should I add/modify in the class?

Please help me,

Thanks in advance.

Ileac answered 29/5, 2014 at 17:57 Comment(9)
Can u explain a bit more..... your requirement?Cottonseed
@Maven I think that I explained my requirement clearly, Do you have any questions regarding my problem?Ileac
u need listview like in instagram ?Cottonseed
I don't know, I edited my question, have a lookIleac
if you already got the two type header like the picture you've put in your question, then what else you want? what's your problem if you've already managed to create that and take a screen shot?!Countless
do you need your black header to be expandable too? and how many black headers are you gonna use?Countless
These 2 type of headers(black,gray) are normal(both are non- clickable & non-expandable),this list is very large consisting of 25 parts, so I want to add another 25 FloatingGroupExpandable headersIleac
well why don't you add two more item types if they are not expandable? you have: TYPE_ITEM , TYPE_SEPARATOR , TYPE_GRAY_SEPARATOR well add TYPE_BLACK_HEADER , TYPE_GRAY_HEADERCountless
no, it should be expandable, if I dont want it to be expandable then ur suggestion would work !Ileac
M
0

try FloatingGroupExpandableListView

I find this to be the best implementation. This use reflection to do the job. Just need to use android GroupExpandableListView and BaseExpandableListAdapter.

List<ContentWrapper> items = new ArrayList<ContentWrapper>();
ContentWrapper group;
for (int i = 1; i <= 14; i++) {
  if (!(q.get(i).getA_name().trim().equals(q.get(i-1).getA_name().trim()))) {
    group = new ContentWrapper(q.get(i).getA_name(), null,null));
  }
  ContentWrapper item = new ContentWrapper(q.get(i).getAS_name(), q.get(i).getDesc_art(),null);
  if(!(q.get(i).getExtra()==null))
     item.setShowGraySeparator();//the gray separator should be merged with item view;
  items.add(item);
}
mAdapter.addGroup(group,items);

public class CustomExpandableListAdapter extends BaseExpandableListAdapter {

    private List<ContentWrapper> mGroups = new ArrayList<ContentWrapper>();
    private List<List<ContentWrapper>> mData = new ArrayList<List<ContentWrapper>>();

    public void addGroup(ContentWrapper group,List<ContentWrapper> items) {
        mGroups.add(group);
        mData.add(items);
    }

    @Override
    public int getGroupCount() {
        // sticky header count
        return mGroups.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        // child count for each group at 'groupPosition'
        mData.get(groupPosition).size();
    }        

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        //sticky header view at 'groupPosition'
        ContentWrapper header = mGroups.get(groupPosition);
        //show group view 
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
       //child view at 'childPosition' for 'groupPosition'
       ContentWrapper item = mData.get(groupPosition).get(childPosition);
       // show item view
    }

}
Mirandamire answered 17/6, 2014 at 10:5 Comment(7)
MyCustomAdapter extends BaseAdapter, & according to FloatingGroupExpandableListView i should extend BaseExpandableListAdapter to MyCustomAdapter, Can you tell me how can it be customised?Ileac
See edit, you need to have a parent/child relation between the sticky header view and normal child viewMirandamire
I understand ur point. The link you provided has a sample project running successfully, But I dont know how to customize it according to MyCustomAdapter, see my code...Ileac
See edit.SeparatorItem should be the group view,GraySeparatorItem should be merged with the item view,visibility controlled by a flag in ContentWrapper.Mirandamire
Can u pls describe more, about the xml, etc ! also I edited my questionIleac
"General","Right to Equality" should be the group view (TextView with fray background).Item view should be a TextView below a gray background View .The Item with childPosition == 0,should have the fray background View visibility = gone.Mirandamire
Black background, Gray Background & white background all sh'd be the child view of the green background(it is floatingGroupExpandableHeader)(relative layout id sample_activity_list_group_item_background)! Views from 1-30 are of part 1 , so green background text is part 1 (floatingGroupExpandableHeader) with childs from 1 to 30 irrespective of the fact weather it is Black Background, Gray Background, or white background ! Then at view 31 I want to add another floatingGroupExpandableHeader with text as part 2 (child views from 31-60), I hope what I am trying to achieve is clear !Ileac
M
-1

Take a look at this implementation: https://github.com/beworker/pinned-section-listview It requires your adapter to implement interface with only one method:

public boolean isItemViewTypePinned(int viewType)

So you could easily integrate this library into your code.

Moran answered 18/6, 2014 at 13:54 Comment(1)
I cant use this librayr,This library dont have much functionality like FloatingGroupExpandableListView which have the property that the child views can be minimized into header onclickIleac

© 2022 - 2024 — McMap. All rights reserved.