单击其外的任何位置时切换“ToggleButton”

时间:2014-04-16 15:38:29

标签: android expandablelistview togglebutton

我有一个列表(ExpandableListView),列表中的每个项目都有一个ToggleButton,它在切换时显示/隐藏子项(子项始终为1,它是一种带有两个按钮的工具栏)。感谢this教程,我可以设置一个自定义按钮而不是expandablelistview的指示器,我这样做是为了除了在单击列表项目时显示工具栏,我还可以做其他事情。此外,我使用this question的答案在打开另一个时自动关闭打开的工具栏。 因此,当触摸屏幕上不是ToggleButton的任何内容时,我需要折叠当前展开的工具栏(即使单击工具栏的某个按钮,我也需要折叠它,只要它自己的“onClick”仍然发送)

这是应用程序的图像:

enter image description here

这是ExpandableListView:

<ExpandableListView
    android:id="@+id/normalList"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:groupIndicator="@drawable/toggle_button_selector" >
</ExpandableListView>

这是组项的xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/filesListDrawerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp" >

<ImageView
    android:id="@+id/img"
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_margin="2dp"
    android:contentDescription="@string/icondescription" />

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="29dp"
    android:layout_alignTop="@+id/img"
    android:layout_marginLeft="15dp"
    android:layout_toRightOf="@+id/img"
    android:gravity="center_vertical"
    android:textAppearance="?android:attr/textAppearanceMedium" />

<TextView
    android:id="@+id/counter"
    android:layout_width="wrap_content"
    android:layout_height="19dp"
    android:layout_alignBottom="@+id/img"
    android:layout_below="@+id/text"
    android:layout_marginLeft="15dp"
    android:layout_toRightOf="@+id/img"
    android:gravity="center_vertical"
    android:textAppearance="?android:attr/textAppearanceSmall" />

<ToggleButton
    android:id="@+id/toggle"
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:layout_alignParentRight="true"
    android:layout_below="@+id/text"
    android:layout_marginRight="15dp"
    android:background="@drawable/toggle_button_selector"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:textColorLink="@android:color/transparent"
    android:textOff=""
    android:textOn="" />

子项:

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

    <TextView
        android:id="@+id/details"
        android:layout_width="0dp"
        android:layout_height="57dip"
        android:layout_weight="1"
        android:clickable="true"
        android:drawableTop="@drawable/ic_action_about"
        android:drawablePadding="-12dp"
        android:background="@drawable/toolbar_selector"
        android:gravity="center"
        android:text="@string/details" />

    <TextView
        android:id="@+id/send"
        android:layout_width="0dp"
        android:layout_height="57dip"
        android:layout_weight="1"
        android:clickable="true"
        android:drawableTop="@drawable/ic_action_new_email"
        android:drawablePadding="-12dp"
        android:background="@drawable/toolbar_selector"
        android:gravity="center"
        android:text="@string/send" />

</LinearLayout>

适配器的相关部分:

public class CustomList extends BaseExpandableListAdapter {

    private final Activity context;
    public final List<Item> names; //Item is a custom Object
    private final Integer[] imageId;
    private int lastExpandedGroupPosition;

    public CustomList(Activity context, List<Item> names, Integer[] imageId) {

        this.context = context;
        this.names = names;
        this.imageId = imageId;
    }

    public View getGroupView(final int position, boolean isExpanded, View convertView, ViewGroup parent) {

        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.list_single, null);
        }

        TextView txtTitle = (TextView) convertView.findViewById(R.id.text);
        TextView txtData = (TextView) convertView.findViewById(R.id.counter);
        ImageView imageView = (ImageView) convertView.findViewById(R.id.img);
        ToggleButton toggle = (ToggleButton) convertView.findViewById(R.id.toggle);
        final ExpandableListView list = (ExpandableListView) parent.findViewById(R.id.normalList);

        txtTitle.setText(names.get(position).getName());

        txtData.setText(names.get(position).getData());

        if(/*some conditions*/) {

            imageView.setImageResource(imageId[0]);
            toggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                    if(isChecked) {

                        list.expandGroup(position, true);

                    } else {

                        list.collapseGroup(position);
                    }
                }
            });

        } else if(/*other conditions*/) {

            imageView.setImageResource(imageId[2]);
            toggle.setVisibility(View.GONE);

        } else {

            imageView.setImageResource(imageId[1]);
            toggle.setVisibility(View.GONE);
        }

        return convertView;
    }

    public View getChildView(int groupPosition, int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {

        if (convertView == null) {

            LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.list_child, null);
        }


        TextView details = (TextView) convertView.findViewById(R.id.details);
        TextView send = (TextView) convertView.findViewById(R.id.send);

        details.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {

                //do something
            }
        });

        send.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {

                //do something else
            }
        });


        return convertView;
    }

    @Override
    public void onGroupExpanded(int groupPosition) {

        ToggleButton button = (ToggleButton) ((ExpandableListView) context
            .findViewById(R.id.normalList)).getChildAt(lastExpandedGroupPosition)
            .findViewById(R.id.toggle);

        if(groupPosition != lastExpandedGroupPosition && button.isChecked()) {
            button.performClick();
        }

        super.onGroupExpanded(groupPosition);
        lastExpandedGroupPosition = groupPosition;
    }
}

最后活动中的重要部分:

lv = (ExpandableListView)findViewById(R.id.normalList);
lv.setGroupIndicator(null);

lv.setOnGroupClickListener(new OnGroupClickListener() {

        public boolean onGroupClick(ExpandableListView parent, View v, int position, long id) {

            //do some things

            return true; //this tells the list that it mustn't show the child items
        }
});

adapter = new CustomList(myActivity.this, list, icons);

lv.setAdapter(adapter);

P.S。:隐藏打开的工具栏的代码无法正常工作,但我真的无法理解为什么。但这是另一个故事......

---编辑---

关于P.S.上图:now I know why that happens

3 个答案:

答案 0 :(得分:1)

您的列表看起来像ExpandableListView。你试过用它吗?它构建了第二级行,扩展,隐藏等。只需将您的pdf行添加为组头,然后将工具行添加为子行。然后,您可以处理行单击以显示和隐藏要显示/隐藏的行。请参阅:http://developer.android.com/reference/android/widget/ExpandableListView.html

而且,顺便说一下,使用隐藏的其他行有点错误的用户体验设计。也许最好使用下拉列表或自定义对话框窗口?它们都具有内置功能,在外面触摸时会消失。

答案 1 :(得分:0)

在ArrayList中填充列表时,您可以简单地放置所有ToggleButton。这样,只需单击其中一个按钮,就可以强制单击列表中的每个按钮。

答案 2 :(得分:0)

好的,我解决了这个问题 我没有在某些方法中使用“performClick()”或“setChecked”切换按钮并管理OnCheckedChangedListener中的展开/折叠操作,而是决定将togglebuttons的状态存储在数组中,并展开/折叠子视图在“getGroupView”方法中,取决于groupview按钮的状态,其在数组中的位置对应于groupview在列表中的位置。要更新列表,我在适配器上调用notifyDataSetChanged()。 我在ToggleButton周围添加了一个FrameLayout来增加其可点击区域。

这是为清晰起见的代码:

MainActivity的相关部分:

public class MainActivity extends ActionBarActivity {

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    .
    .
    .

    ExpandableListView lv = (ExpandableListView) findViewById(R.id.normalList);
    CustomList adapter = new CustomList(MainActivity.this, list /*the list of Items, declared elsewhere*/, lv);
    lv.setAdapter(adapter);
    DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.filesListDrawerLayout);

    lv.setOnGroupClickListener(new OnGroupClickListener() {

        public boolean onGroupClick(ExpandableListView parent, View v, int position, long id) {

            uncheckButtons(mDrawerLayout);

            //do some unrelated stuff

            return true;
        }
    });
}

public void uncheckButtons(ViewGroup vg) {

    for(int i = 0; i < adapter.buttons.length; ++i)
        adapter.buttons[i] = false;

        adapter.lastChecked = -1;

        adapter.notifyList();
}

适配器的相关部分:

public class CustomList extends BaseExpandableListAdapter {

private final Activity context;
public final List<Item> names; //Item is a custom Object
public boolean[] buttons;
public int lastChecked;
private final Integer[] imageId = new Integer[] { R.drawable.image1, R.drawable.image1, R.drawable.image3 };
private ExpandableListView list;

public CustomList(Activity context, List<Item> names, boolean forUpload, ExpandableListView list) {

    this.context = context;
    this.names = names;
    this.list = list;
    this.buttons = new boolean[names.size()];
    this.lastChecked = -1;
}

private static class GroupHolder {

    TextView txtTitle;
    TextView txtData;
    ImageView imageView;
    ToggleButton toggle;
    FrameLayout frame;
}

public View getGroupView(final int position, boolean isExpanded, View convertView, ViewGroup parent) {

    GroupHolder holder;

    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.list_single, null);

        holder.txtTitle = (TextView) convertView.findViewById(R.id.text);
        holder.txtData = (TextView) convertView.findViewById(R.id.counter);
        holder.imageView = (ImageView) convertView.findViewById(R.id.img);
        holder.toggle = (ToggleButton) convertView.findViewById(R.id.toggle);
        holder.frame = (FrameLayout) convertView.findViewById(R.id.frame);

        convertView.setTag(holder);

    } else {

        holder = (GroupHolder) convertView.getTag();
    }

    txtTitle.setText(names.get(position).getName());

    txtData.setText(names.get(position).getData());

    if(/*some conditions*/) {

        imageView.setImageResource(imageId[0]);

        holder.frame.setOnTouchListener(new OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {

                if(event.getAction() == MotionEvent.ACTION_UP) {

                    if(lastChecked != -1) {//if there's a checked button
                    buttons[lastChecked] = !buttons[lastChecked];//uncheck it

                    if(position == lastChecked)//if I clicked on the last checked button 
                        lastChecked = -1;//there's no checked button
                    else {
                        buttons[position] = !buttons[position];//check the button
                        lastChecked = position;//and set it as the last checked one
                    }

                    notifyList();
                }

                return false;
            }
        });

        holder.toggle.setChecked(buttons[position]);

        if(holder.toggle.isChecked()) {

            if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2)
                list.expandGroup(position);
            else
                list.expandGroup(position, true);
        } else {

            list.collapseGroup(position);
        }

    } else if(/*other conditions*/) {

        //do other stuff with the views that don't interest us
    }

    return convertView;
}

private static class ChildHolder {

    TextView details;
    TextView send;
    TextView other;
}

public View getChildView(final int groupPosition, int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {

    ChildHolder holder;

    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.list_child, null);

        holder = new ChildHolder();

        holder.details = (TextView) convertView.findViewById(R.id.details);
        holder.send = (TextView) convertView.findViewById(R.id.send);
        holder.other = (TextView) convertView.findViewById(R.id.other);

    } else {

        holder = (ChildHolder) convertView.getTag();
    }

    //maybe I could manage the listeners more nicely and without redundance...

    holder.details.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {

            buttons[lastChecked] = !buttons[lastChecked];//uncheck the only checked button (it always exists at this point)
            lastChecked = -1;//there's no checked button
            notifyList();

            //call a certain method in the main activity...
        }
    });

    holder.send.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {

            buttons[lastChecked] = !buttons[lastChecked];//uncheck the only checked button (it always exists at this point)
            lastChecked = -1;//there's no checked button
            notifyList();

            //call a certain method in the main activity...
        }
    });

    holder.other.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {

            buttons[lastChecked] = !buttons[lastChecked];//uncheck the only checked button (it always exists at this point)
            lastChecked = -1;//there's no checked button
            notifyList();

            //call a certain method in the main activity...
        }
    });

    return convertView;
}

public void notifyList() {

    this.notifyDataSetChanged();
}

//I don't need OnGroupExpanded anymore

ExpandableListView:

<ExpandableListView
    android:id="@+id/normalList"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:choiceMode="singleChoice"
    android:groupIndicator="@drawable/toggle_button_selector" >
</ExpandableListView>

组项的xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/filesListDrawerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp" >

<ImageView
    android:id="@+id/img"
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="2dp"
    android:layout_marginTop="2dp"
    android:layout_marginBottom="2dp"
    android:contentDescription="@string/icondescription" />

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="29dp"
    android:layout_alignTop="@+id/img"
    android:layout_marginLeft="15dp"
    android:layout_toRightOf="@+id/img"
    android:gravity="center_vertical"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:textColor="@color/black" />

<TextView
    android:id="@+id/counter"
    android:layout_width="wrap_content"
    android:layout_height="19dp"
    android:layout_alignBottom="@+id/img"
    android:layout_below="@+id/text"
    android:layout_marginLeft="15dp"
    android:layout_toRightOf="@+id/img"
    android:gravity="center_vertical"
    android:textAppearance="?android:attr/textAppearanceSmall"
    android:textColor="@color/black" />

<FrameLayout
    android:id="@+id/frame"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_below="@+id/text"
    android:layout_marginTop="-15dp"
    android:clickable="true"
    android:paddingTop="10dp"
    android:paddingRight="15dp"
    android:paddingLeft="10dp" >

    <ToggleButton
        android:id="@+id/toggle"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:background="@drawable/toggle_button_selector"
        android:clickable="false"
        android:duplicateParentState="true"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:textColorLink="@android:color/transparent"
        android:textOff=""
        android:textOn="" />

</FrameLayout>

</RelativeLayout>

子项的xml:

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

    <TextView
        android:id="@+id/details"
        android:layout_width="0dp"
        android:layout_height="57dip"
        android:layout_weight="1"
        android:clickable="true"
        android:drawableTop="@drawable/ic_action_about"
        android:drawablePadding="-12dp"
        android:background="@drawable/toolbar_selector"
        android:gravity="center"
        android:text="@string/details" />

    <TextView
        android:id="@+id/send"
        android:layout_width="0dp"
        android:layout_height="57dip"
        android:layout_weight="1"
        android:clickable="true"
        android:drawableTop="@drawable/ic_action_new_email"
        android:drawablePadding="-12dp"
        android:background="@drawable/toolbar_selector"
        android:gravity="center"
        android:text="@string/send" />

    <!-- this one is new -->
    <TextView
        android:id="@+id/other"
        android:layout_width="0dp"
        android:layout_height="57dip"
        android:layout_weight="1"
        android:background="@drawable/toolbar_selector"
        android:clickable="true"
        android:drawablePadding="-12dp"
        android:drawableTop="@drawable/ic_action_other"
        android:gravity="center"
        android:text="@string/other" />

</LinearLayout>

有。我现在很高兴。