【问题标题】:Toggle a "ToggleButton" when clicking anywhere outside it单击“ToggleButton”外部的任何位置时切换它
【发布时间】:2014-05-31 14:19:11
【问题描述】:

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

这是应用程序的图片:

这是 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.

【问题讨论】:

    标签: android expandablelistview togglebutton


    【解决方案1】:

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

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

    【讨论】:

    • 哦,哇,我不知道它存在。我一定会尝试的,但是明天,我现在没时间了>_>谢谢! 编辑:好的,我试过了,但是:1- 将指示器设置在正确的位置很痛苦; 2-我无法做到,因此我可以单击列表项进行某些操作,并且仅在单击指示器时显示子项。如果有人知道我该怎么做,我将不胜感激......
    • 好的,我解决了问题。我按照this 教程设置自定义按钮而不是指示器,并在单击列表项时执行除显示工具栏之外的其他操作,我使用this question 的答案在打开另一个工具栏时自动关闭打开的工具栏.现在剩下的就是在单击按钮以外的任何位置时关闭打开的工具栏。
    • 我应该编辑问题以反映当前情况吗?
    • 您应该在原始问题中添加一些空格('----edit----')后的当前情况。如果您认为我的回答有用,您也可以点赞。
    • 哇,真的。在这种情况下,删除过时的部分可能会更好。请记住,此站点会保存您的更改历史记录,因此任何有兴趣的人都可以找到您帖子的旧版本。您也可以考虑添加一个新问题,但我猜它会非常相似
    【解决方案2】:

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

    【讨论】:

    • 是的,我已经考虑过这一点,我可能会将其作为临时的部分解决方案,但我需要在单击屏幕上任意位置时关闭工具栏,保存在选中的切换按钮上,而不仅仅是另一个项目的切换按钮。
    • 令我惊讶的是您使用按钮单击事件而不是默认单击列表元素。放置自定义按钮时它不起作用吗?因为基本上 ListView 的每个元素中都已经包含了一个事件,并且它应该覆盖列表每一行内的所有对象。
    • 我的错,事实上你没有使用 ListView。您应该考虑将这些元素放在一个列表中。
    • 点击列表中的一个元素会打开文件,所以我不能使用它。我将在问题中添加此信息。是的,我使用列表视图,但我发布的 xml 是单个列表元素之一。
    【解决方案3】:

    好的,我解决了这个问题。
    我没有在某些方法中使用“performClick()”或“setChecked”切换按钮并在 OnCheckedChangedListener 中管理展开/折叠操作,而是决定将切换按钮的状态存储在一个数组中,并展开/折叠子视图在“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>
    

    那里。我现在很开心。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-02
      • 2011-08-24
      • 2012-08-29
      • 2015-10-24
      • 2016-04-19
      相关资源
      最近更新 更多