ApiDemos--FragmentContextMenu的例子分析

ApiDemos--FragmentContextMenu的例子分析

 

ContextMenu顾名思义就是上下文菜单的意思,在某些情况下,我们是需要这样的菜单的,这个菜单通常会和某个View绑定在一起。在Fragment中定义上下文菜单的步骤如下:

1)调用registerForContextMenu(View view)来绑定某个View对象;

2) 然后实现回调onCreateContextMenu,在显示上下文菜单之前,会调用此方法。在这个回调中填充ContextMenu对象,指定要显示的菜单条目;

3) 实现回调方法onContextItemSelected(),来响应菜单事件。

 

FragmentContextMenu类在布局的android.R.id.content中添加了一个Fragment,代码如下:

@Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
 
       // Create the list fragment and add it asour sole content.
       ContextMenuFragment content = new ContextMenuFragment();       getFragmentManager().beginTransaction().add(android.R.id.content, content).commit();
    }

 

这样这个Fragment就会显示在Activity中了。如果你对android.R.id.content感到困惑的话,最后我会简要说明一下此乃何物。

 

在ContextMenuFragment中我们在某个Button上注册了一个上下文菜单:

@Override
        public View onCreateView(LayoutInflater inflater,ViewGroup container,
                Bundle savedInstanceState) {
            View root =inflater.inflate(R.layout.fragment_context_menu, container, false);
           registerForContextMenu(root.findViewById(R.id.long_press));
            return root;
       }

 

然后实现回调onCreateContextMenu(),来填充菜单:

@Override
        public void onCreateContextMenu(ContextMenu menu, Viewv, ContextMenuInfo menuInfo) {
            super.onCreateContextMenu(menu, v, menuInfo);
            /*menu.add(Menu.NONE, R.id.a_item, Menu.NONE, "Menu A");
            menu.add(Menu.NONE, R.id.b_item,Menu.NONE, "Menu B");*/
           getActivity().getMenuInflater().inflate(R.menu.fragment_context_menu, menu);
        }


原代码的例子是直接使用menu.add()的形式来填充菜单,但是我觉得这种形式相当不好,不够灵活,我修改成使用资源填充的形式,当然需要在/res/menu/目录下创建一个fragment_context_menu.xml文件:

<?xml version="1.0"encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/a_item"android:title="菜单A"></item>
    <item android:id="@+id/b_item"android:title="菜单B"></item>
</menu>

 

然后响应菜单点击事件:

@Override
        public boolean onContextItemSelected(MenuItemitem) {
            switch (item.getItemId()) {
                case R.id.a_item:
                    Toast.makeText(getActivity(),"Item 1a was chosen", Toast.LENGTH_SHORT).show();
                    return true;
                case R.id.b_item:
                    Toast.makeText(getActivity(),"Item 1b was chosen", Toast.LENGTH_SHORT).show();
                    return true;
            }
            return super.onContextItemSelected(item);
        }

 

长按按钮显示出来的上下文菜单的效果图如下:

 


下面我们来谈一谈android.R.id.content是个什么东西。从它的使用上来看,这个content其实是布局文件中某个View的id。在Activity的回调onCreate()中我们通常会调用setContentView来设置布局文件,这个setContentView的实现在Activity.java中形式如下:

 

public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
        initActionBar();
    }

 

getWindow()其实是一个PhoneWindow对象,它的setContentView()的实现如下:

@Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

 

从上面的代码我们可以知道,通常情况下我们设置的界面布局文件layoutResID会被添加到mContentParent中去,在installDecor()中mContentParent会被创建出来:

private void installDecor(){
       。。。
if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

 

然后我们进入generateLayout()中看一看:

protected ViewGroup generateLayout(DecorView decor) {
        // Apply data from current theme.
。。。
View in = mLayoutInflater.inflate(layoutResource,null);
        decor.addView(in, newViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
 
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        if (contentParent == null) {
            throw new RuntimeException("Window couldn't find content container view");
        }
。。。
return contentParent;
}


这个contentParent就是ID为ID_ANDROID_CONTENT的ViewGroup对象,而这个ID值就是等于android.R.id.content,原来我们上面的Fragment添加到了这个ViewGroup对象中去了。其实那个View in对象就是我们整个activity界面的布局,包括ActionBar,content等对象。layoutResource根据当前设置的Feature不同,会得到不同的值,通常情况下这个值等于layoutResource = com.android.internal.R.layout.screen_action_bar;

而这个布局文件的内容如下:

/android/frameworks$ cat./base/core/res/res/layout/screen_action_bar.xml

<com.android.internal.widget.ActionBarOverlayLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/action_bar_overlay_layout"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:splitMotionEvents="false">
    <FrameLayout android:id="<span style="color:#ff6666;">@android:id/content</span>"
                android:layout_width="match_parent"
                 android:layout_height="match_parent"/>
   <com.android.internal.widget.ActionBarContainer
       android:id="@+id/action_bar_container"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentTop="true"
        android:layoutDirection="ltr"
       style="?android:attr/actionBarStyle"
        android:gravity="top">
       <com.android.internal.widget.ActionBarView
           android:id="@+id/action_bar"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           style="?android:attr/actionBarStyle" />
       <com.android.internal.widget.ActionBarContextView
           android:id="@+id/action_context_bar"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
            android:visibility="gone"
           style="?android:attr/actionModeStyle" />
   </com.android.internal.widget.ActionBarContainer>
   <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 style="?android:attr/actionBarSplitStyle"
                 android:visibility="gone"
                 android:gravity="center"/>
</com.android.internal.widget.ActionBarOverlayLayout>

上图中标红的就是那个android.R.id.content对象。

 

请参考完整源码

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值