Android: start an intent into a framelayout

2019-02-15 13:09发布

问题:

I have a main activity with this layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_height="fill_parent"
  android:layout_width="fill_parent"
  android:orientation="vertical"
  android:id="@+id/container"
  >
    <LinearLayout
        android:layout_height="wrap_content"
        android:id="@+id/header" 
        android:background="@drawable/logo_bk"
        android:layout_width="fill_parent"
    >

    <Button 
        android:id="@+id/btn_reload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Reload" 
     />

     <LinearLayout 
        android:id="@+id/LinearLayout01" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
        android:gravity="center_vertical|center_horizontal"
     >
        <ImageView 
            android:id="@+id/ImageView01" 
            android:src="@drawable/logo_head" 
            android:scaleType="fitStart" 
            android:adjustViewBounds="true" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" />
     </LinearLayout>

    </LinearLayout>

    <FrameLayout 
        android:id="@+id/center" 
        android:layout_height="fill_parent" 
        android:layout_width="fill_parent" 
        android:layout_weight="1">
    </FrameLayout>

    <LinearLayout 
        android:layout_height="fill_parent" 
        android:layout_width="fill_parent" 
        android:gravity="center" 
        android:id="@+id/footer"
        android:layout_weight="2.6"
        android:background="#ffffff">
    </LinearLayout>

</LinearLayout>

Basically it is composed of a header, a central part (android:id="@+id/center") and a footer. The footer contains four dynamically created buttons. At the end it looks like a TabWidget with the tabs at the bottom.

Each footer's buttons holds an intent/activity.

The question is: How can I start my activity into the FrameLayout? For instance TabHost does this:

spec = tabHost
        .newTabSpec(tabTitle.toLowerCase())
        .setIndicator(tabTitle,res.getDrawable(R.drawable.tab_spec))
        .setContent(intent);
        tabHost.addTab(spec);

回答1:

If you have separate activities for each page you want to display, you're going to have to extend ActivityGroup for the container activity (the one displaying the tabs), and LocalActivityManager to manage the different embedded activities you want to use.

It's kind of complicated, and not documented. I had to read the sourcecode for TabHost.

Search for class IntentContentStrategy.

Basically, the idea is that you have a container view, and you use LocalActivityManager to load the activity, get it's View, and place it inside the container view.

Excerpt from TabHost.java:

    public View getContentView() {
        if (mLocalActivityManager == null) {
            throw new IllegalStateException("Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?");
        }
        final Window w = mLocalActivityManager.startActivity(
                mTag, mIntent);
        final View wd = w != null ? w.getDecorView() : null;
        if (mLaunchedView != wd && mLaunchedView != null) {
            if (mLaunchedView.getParent() != null) {
                mTabContent.removeView(mLaunchedView);
            }
        }
        mLaunchedView = wd;

        // XXX Set FOCUS_AFTER_DESCENDANTS on embedded activities for now so they can get
        // focus if none of their children have it. They need focus to be able to
        // display menu items.
        //
        // Replace this with something better when Bug 628886 is fixed...
        //
        if (mLaunchedView != null) {
            mLaunchedView.setVisibility(View.VISIBLE);
            mLaunchedView.setFocusableInTouchMode(true);
            ((ViewGroup) mLaunchedView).setDescendantFocusability(
                    FOCUS_AFTER_DESCENDANTS);
        }
        return mLaunchedView;
    }

Note: there is a lot of tweaking and weird stuff you have to do to get this stuff to work (notice the bug they reference in the comment there), which is probably why it's not documented.