Android:如何在创建列表时禁用列表项

Posted

技术标签:

【中文标题】Android:如何在创建列表时禁用列表项【英文标题】:Android: How to disable list items on list creation 【发布时间】:2011-01-12 02:53:39 【问题描述】:

我对 android 开发人员还很陌生,并且还在做很多事情。

我有一个使用以下代码显示的主菜单,但不知道如何禁用菜单中的选定项目。谁能帮我提供一些示例代码?

public class listTest extends ListActivity 

    @Override
    public void onCreate(Bundle savedState) 
        super.onCreate(savedState);
        setListAdapter(ArrayAdapter.createFromResource(this, R.array.mainMenu,
                android.R.layout.simple_list_item_1)); 
        //not sure how to disable list items here
    

    protected void onListItemClick(ListView list, View view, int position, long id) 
        // can disable items when they are clicked on
        view.setEnabled(false);
       


我的 strings.xml 文件中有一个string-array

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="mainMenu">
        <item>Item 1</item>
        <item>Item 2</item>
        <item>Item 3</item>
    </string-array> 
</resources>

谢谢

【问题讨论】:

几个快速澄清:如果你想要一个菜单​​,当用户按下菜单键时会弹出一个菜单,然后检查 Activity 中的 onCreateOptionsMenu 方法。此外,您不需要像那样保留应用程序上下文;一个Activity 已经扩展了Context(正如您在对createFromResource(this, ...) 的调用中看到的那样。 我想要一个在应用程序首次打开时显示的主菜单,因此 optionsMenu 和 contextMenu 没有任何好处。我已经显示了列表,并且可以在单击项目时禁用它们: protected void onListItemClick(ListView list, View view, int position, long id) view.setEnabled(false);但我不知道如何在 onCreate 中将选定的列表项设置为禁用。注意应用程序上下文 - 谢谢。 【参考方案1】:

为了在创建列表时禁用列表项,您必须从 ArrayAdapter 继承子类。您必须覆盖以下方法:isEnabled(int position)areAllItemsEnabled()。在以前,您返回truefalse,具体取决于是否启用给定位置的列表项。在后者中,您返回false

如果您想使用createFromResource(),您也必须实现该方法,因为ArrayAdapter.createFromResource() 仍然实例化ArrayAdapter 而不是您自己的适配器。

最后,代码如下所示:

class MenuAdapter extends ArrayAdapter<CharSequence> 

    public MenuAdapter(
            Context context, int textViewResId, CharSequence[] strings) 
        super(context, textViewResId, strings);
    

    public static MenuAdapter createFromResource(
            Context context, int textArrayResId, int textViewResId) 

        Resources      resources = context.getResources();
        CharSequence[] strings   = resources.getTextArray(textArrayResId);

        return new MenuAdapter(context, textViewResId, strings);
    

    public boolean areAllItemsEnabled() 
        return false;
    

    public boolean isEnabled(int position) 
        // return false if position == position you want to disable
    

【讨论】:

小心这个解决方案。 BaseAdapter 的文档指出以下“如果指定位置的项目不是分隔符,则返回 true”。这意味着如果您返回 false,则该项目是分隔项目。有些手机可能不会在普通项目和分隔项目之间绘制 android:divider。 @Janusz 是的,我遇到了分隔线的问题,因为当我在某个索引处禁用该项目时,分隔线消失了。所以我让索引处的视图有点灰色,看起来被禁用了:) @AliImran:您能否详细说明一下您是如何在未绘制分隔线的情况下处理此问题的?谢谢【参考方案2】:

我相信列表项是否启用是该项状态的一部分,所以我猜你必须在ListAdapter 中管理它。子类化适配器时,您可以覆盖isEnabled(position)。对于您在此处返回 true 的任何位置,ListView 都会将此项目标记为禁用。

所以你想做的是这样的:

class MenuAdapter extends ArrayAdapter<String> 

    public boolean isEnabled(int position) 
       // return false if position == positionYouWantToDisable
    


这可能需要例如Map 管理每个项目的启用状态,如果您希望能够使用设置器启用/禁用项目。

然后在您的 ListView 上设置自定义适配器。

【讨论】:

感谢您的回复,这看起来不错,但在实施时遇到了问题。 setListAdapter(MenuAdapter.createFromResource(this, R.array.mainMenu,android.R.layout.simple_list_item_1)); MenuAdapter mainMenuList = (MenuAdapter) getListAdapter(); mainMenuList.isEnabled(2); //只是设置为返回 false atm 我哪里出错了有什么想法吗?它目前只是崩溃 那么,你得到的异常是什么? 02-03 13:51:21.971: 错误/AndroidRuntime(1365): java.lang.RuntimeException: 无法启动活动 ComponentInfocom.martyn.test/com.martyn.test.test : java.lang.ClassCastException: android.widget.ArrayAdapter 在哪一行? setListAdapter(MenuAdapter.createFromResource(this, R.array.mainMenu,android.R.layout.simple_list_item_1));?这很奇怪,因为 createFromResource 返回一个 ArrayAdapter,而 ArrayAdapter 是一个 ListAdapter。尝试手动实例化它,而不是使用资源助手。 不应该是'对于任何职位,你在这里返回 FALSE'?【参考方案3】:

您可以通过调用两者来禁用列表项(= 使其不响应触摸)

setClickable(false)

setFocusable(false)

例如在您的适配器中。

不过,默认情况下,这不会自动以图形方式反映。

我目前在一个列表中使用它,其列表项不可点击,但其中大部分包含可点击的小部件。效果很好。

这样,列表项的绘制通常包括分隔符(请参阅 Janusz 对上述已接受答案的回复)。

【讨论】:

您能说得更具体些吗?您在适配器的哪个位置调用它?你的回答看起来很有希望,但我不知道如何实现它...... 我已经实现了BaseAdapter 的一个子类,它在其getView 方法中扩展了列表单元格布局。在布局 XML 中,根元素(在我的例子中)是一个既不可聚焦也不可点击的 LinearLayoutandroid:focusable="false"android:clickable="false" 您也可以在适配器的getView 方法中的代码中执行此操作,方法是在代表您的列表项的视图上调用setClickable(false)setFocusable(false) 我尝试了您的解决方案并且它有效,但很明显,相反!我有这个:public View getView(int position, View convertView, ViewGroup parent) View row = convertView; if (row == null) row = inflater.inflate(R.layout.row_style, parent, false); row.setFocusable(false); row.setClickable(false); return row; 这使我的所有行都启用(可点击)。但是如果我使用 row.setFocusable(true); row.setClickable(true); 行是不可点击的。很奇怪…… 对于所有认为该行为反向起作用的人来说,事实并非如此。当您使列表项可单击(true)时,随后的单击将传递到列表项本身,因此该事件不会传播到父项(listview)。如果列表项对点击没有反应,则什么也不会发生。【参考方案4】:

或者以简单的方式取消注册并注册 OnItemClickListener 可能是一个更好的主意。

注册:

lstDevice.setOnItemClickListener(context);

注销:

lstDevice.setOnItemClickListener(null);

【讨论】:

以上是关于Android:如何在创建列表时禁用列表项的主要内容,如果未能解决你的问题,请参考以下文章

如何根据字符串值禁用列表视图项?

如何在不禁用列表项的命中测试的情况下启用对列表项的选择?

如何在android中的活动开始时禁用按钮的单击事件检查

在我的菜单项之后,如何禁用“文件”菜单中的文档列表?

MFC - 如何禁用列表项?

Android 如何在阅读列表项计数时停止包含页脚行的 TalkBack