Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
269 views
in Technique[技术] by (71.8m points)

android - Make fragments full screen programmatically

I have a ViewPager and FragmentPagerAdapter set up in one activity with 3 fragments. All fragments are loaded simultaneously and are kept in memory using

mPager.setOffscreenPageLimit(2);

One of these fragments hosts a camera preview that I would like to make full screen, with no status bar or action bar. The other fragments require that the action bar be displayed.

How would I make only the camera preview fragment full screen while keeping the other two fragments normal? I have tried using themes, which means breaking the action bar.

Programmatically calling the following doesn't help, because it forces the whole activity to be full screen (and thus the other two fragments along with it):

requestWindowFeature(Window.FEATURE_NO_TITLE); 
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);

I also tried implementing ViewPager.OnPageChangeListener:

public void onPageSelected(int position) {
    if(position == 1)
        getActionBar().hide();
    else
        getActionBar().show();
}

This does hide the action bar, but it doesn't hide the system status bar (I'm talking about where the notifications, status icons, and time are), and the action bar hide/show animation is also very choppy when swiping.

For an example of what I want to do exactly, see Snapchat - they manage to pull off the swiping between camera and other fragments perfectly.

Edit:

So I changed my onPageSelected to this:

public void onPageSelected(int position) {
    if(position == 1) {
        MainActivity.this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        MainActivity.this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    } else {
        MainActivity.this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        MainActivity.this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    }
}

This enables me to change whether the status bar is displayed or not. However, it causes a large amount of jank. Same problem with the action bar.

I notice that in Snapchat the status bar slides up and down after the tab change is complete. I'm not sure how to implement this, so any advice regarding this aspect would be appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I figured out how to do this, though it's definitely a hack.

The trick is not to use the Android action bar, it's to make your own in your layout files.

I defined two more RelativeLayouts in my code:

<RelativeLayout
    android:id="@+id/padding"
    android:layout_width="fill_parent"
    android:layout_height="25dip"
    android:layout_alignParentTop="true"
    android:background="@color/abs__background_holo_dark" />

<RelativeLayout
    android:id="@+id/fake_action_bar"
    android:layout_width="fill_parent"
    android:layout_height="48.0dip"
    android:layout_below="@id/padding" >

<!-- stuff here -->

</RelativeLayout>

The top RelativeLayout is padding for the Android status bar. I set it to 25dip, but it may vary - it would probably be best to set this value programmatically. Also you need to set it to a black color so that it matches the status bar color and makes the UI look more natural.

The bottom RelativeLayout is for your fake action bar. You need to stuff everything your action bar needs (title text, buttons, etc.) in this RelativeLayout. I set it to 48dip, but again, this will vary and you should probably set it programmatically.

In the Activity hosting your Fragments, ViewPager and FragmentPagerAdapter, you need to set the flags telling Android to make the status bar an overlay:

WindowManager.LayoutParams params = getWindow().getAttributes();
params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;

Now we need to make the status bar hide and show when we switch fragments. Have your activity implement ViewPager.OnPageChangeListener and then use the following code:

@Override
public void onPageScrollStateChanged(int state) {
    switch(state) {
    case ViewPager.SCROLL_STATE_IDLE:
        if(mPosition == 1) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        } else {
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        }
    }
}

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {
    mPosition = position;
}

We keep track of the page number using onPageSelected and use it in onPageScrollStateChanged to dynamically hide/show the status bar depending on which Fragment is currently being displayed. You can't do this in onPageSelected because this will cause the status bar to redisplay halfway through a swipe.

You also need to make sure to add appropriate code for your fake action bar - for buttons, this would be OnClickListener.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...