Search code examples
javaandroideclipseexpandablelistview

Changing the location of indicator in ExpandableListView causing problems


I'm trying to set my indicator to be next to the textview, but I just can't get the right code to do it.

XML:

<TextView
    android:id="@+id/lblListHeader"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
    android:textColor="#000000"
    android:textSize="17dp" />

<ImageView
    android:id="@+id/imageView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_toLeftOf="@+id/lblListHeader"
    android:src="@drawable/custom_arrow" />

This is the only stack of code that I have found researching but I can't get it to work:

//inside getGropView method
View v;
    if (convertView == null) {
        v = newGroupView(isExpanded, parent);
    } else {
        v = convertView;
    }
    bindView(v, mGroupData.get(groupPosition), mGroupFrom, mGroupTo);
    ((ImageView) v.findViewById(R.id.videos_group_indicator))
    .setImageResource(isExpanded?R.drawable.videos_chevron_expanded:R.drawable.videos_chevron_collapsed);
    return v;

The main problem is that it "underlines" the newGroupView method etc. because I don't have such method and it is not mentioned how to create it in the example I was looking at.

Also, once I get the solution, could someone please try and explain this code to me? I have read it through a lot of time and I just can't get myself to understand it, I'm a beginner.


Solution

  • Here's an example of custom expandable list view:

    What you want to see if you apply this code in your new project:

    enter image description here

    create this code into activity

    public class ExpActivity extends Activity
    {
    
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            // Находим наш list 
            ExpandableListView listView = (ExpandableListView)findViewById(R.id.exListView);
    
            //Создаем набор данных для адаптера        
            ArrayList<ArrayList<String>> groups = new ArrayList<ArrayList<String>>();
            ArrayList<String> children1 = new ArrayList<String>();
            ArrayList<String> children2 = new ArrayList<String>();
            children1.add("Child_1");
            children1.add("Child_2");
            groups.add(children1);
            children2.add("Child_1");
            children2.add("Child_2");
            children2.add("Child_3");
            groups.add(children2);       
           //Создаем адаптер и передаем context и список с данными
            ExpListAdapter adapter = new ExpListAdapter(getApplicationContext(), groups);
            listView.setAdapter(adapter);
        }
    } 
    

    add expandableListView into main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    <ExpandableListView
            android:id="@+id/exListView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:indicatorLeft="250dp"
            android:indicatorRight="300dp"
        />
    </LinearLayout>
    

    create an adapter class

    public class ExpListAdapter extends BaseExpandableListAdapter {
    
        private ArrayList<ArrayList<String>> mGroups;
        private Context mContext;
    
        public ExpListAdapter (Context context,ArrayList<ArrayList<String>> groups){
            mContext = context;
            mGroups = groups;
        }
    
        @Override
        public int getGroupCount() {
            return mGroups.size();
        }
    
        @Override
        public int getChildrenCount(int groupPosition) {
            return mGroups.get(groupPosition).size();
        }
    
        @Override
        public Object getGroup(int groupPosition) {
            return mGroups.get(groupPosition);
        }
    
        @Override
        public Object getChild(int groupPosition, int childPosition) {
            return mGroups.get(groupPosition).get(childPosition);
        }
    
        @Override
        public long getGroupId(int groupPosition) {
            return groupPosition;
        }
    
        @Override
        public long getChildId(int groupPosition, int childPosition) {
            return childPosition;
        }
    
        @Override
        public boolean hasStableIds() {
            return true;
        }
    
        @Override
        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
                                 ViewGroup parent) {
    
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.group_view, null);
            }
    
            if (isExpanded){
               //Изменяем что-нибудь, если текущая Group раскрыта
            }
            else{
                //Изменяем что-нибудь, если текущая Group скрыта
            }
    
            TextView textGroup = (TextView) convertView.findViewById(R.id.textGroup);
            textGroup.setText("Group " + Integer.toString(groupPosition));
    
            return convertView;
    
        }
    
        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                                 View convertView, ViewGroup parent) {
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.child_view, null);
            }
    
            TextView textChild = (TextView) convertView.findViewById(R.id.textChild);
            textChild.setText(mGroups.get(groupPosition).get(childPosition));
    
            Button button = (Button)convertView.findViewById(R.id.buttonChild);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(mContext,"button is pressed",5000).show();
                }
            });
    
            return convertView;
        }
    
        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return true;
        }
    }
    

    the names of methods and parameters is quite informative. methods getGroupView and getChildView returns View for pparents and children accordingly. using the parameter isExpanded in the method getGroupView, we ca, for instance, change the back of group in different states. using LayoutInflater we use custom layout for our list.

    group_view.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">
        <TextView
                android:id="@+id/textGroup"
                android:layout_width="wrap_content"
                android:layout_height="50dp"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="20dp"
                android:textColor="@android:color/white"
                android:textStyle="bold"
                />
    </LinearLayout>
    

    child_view.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">
      <TextView
         android:id="@+id/textChild"
         android:layout_width="wrap_content"
         android:layout_height="40dp"
         android:layout_marginLeft="20dp"
         android:layout_marginTop="20dp"
         android:textColor="@android:color/white"
         />
      <Button
         android:id="@+id/buttonChild"
         android:layout_width="100dp"
         android:layout_height="40dp"
         android:layout_marginLeft="150dp"
         android:layout_marginTop="10dp"
         android:text="Button"
         android:focusable="false"
         />
    </LinearLayout>
    

    in the child view we added a button, in the adapter method getChildView controlling its pressed. in the similar way we can add buttons and other elements in group_view.xml .

    also, we can pin listeners to our list.

    •OnChildClickListener — pressing on an element •OnGroupCollapseListener – collapsing group •OnGroupExpandListener – expanding group •OnGroupClickListener – press on group

    now lets look at groupIndicater - indicator of the group state. it's placement pointed in main.xml with parameters indicatorLeft, indicatorRigh - corresponding to left and right border. by default the indicator placed on the left side, what is not so cool.

    also we can add custom images, for that, we need to add indicator.xml in the folder drawable with this code.

    <?xml version="1.0" encoding="utf-8"?>
    
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_expanded="true"
              android:drawable="@drawable/imageOpen">
        </item>
        <item android:state_empty="true"
              android:drawable="@drawable/imageClose">
        </item>
    </selector>
    

    where imageOpen is for expanded group imageClose is for collapsed group

    next time we need to add a row for parameters of our list in main.xml

    android:groupIndicator="@drawable/indicator"