2

我开发了一个三窗格布局,一次最多可以看到两个窗格。仅在横向模式下支持多个视图。每个窗格都包含用于更改可见性状态的箭头,因此窗格分布会发生变化。

当应用程序以纵向模式打开时,视图转换正常工作。当应用程序以横向模式打开时,也会发生同样的情况。当设备旋转并且控件应该改变面板的分布时会出现问题。当设备旋转时,状态转换失败,窗格消失或不在应有的位置。

由于应用程序的要求,活动主机自己处理配置更改(android:configChanges="orientation|screensize"),我无法禁用此行为。当onConfigurationChanged在宿主活动中调用方法时,通知控件执行状态转换。根据当前可见性状态和新方向,控件确定新状态并调用负责执行转换的configureWidth方法(控件代码中的方法)。下面是宿主活动和控件的代码:

MainActivity.java

public class MainActivity extends Activity implements
    CategoriesListFragment.OnCategoriesListSizeControlListener,
    TasksListFragment.OnTasksListSizeControlListener,
    TaskDetailFragment.OnTaskDetailSizeControlListener, OnStateChangeListener {

    // Multipanel control that will contain the fragments associated with the 
    // category list, task list and task detail.
    private ThreePaneLayout mMultiPaneControl;

    // Fragments
    private CategoriesListFragment mCategoriesListFragment;
    private TasksListFragment mTasksListFragment;
    private TaskDetailFragment mTaskDetailFragment;

    private int mScreenOrientation;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Get the initial orientation of the device
        mScreenOrientation = getResources().getConfiguration().orientation;

        mMultiPaneControl = (ThreePaneLayout) findViewById(R.id.multiPaneControl);

        mCategoriesListFragment = CategoriesListFragment.newInstance();
        mTasksListFragment      = TasksListFragment.newInstance();
        mTaskDetailFragment     = TaskDetailFragment.newInstance();

        // Add the state change observers of the ThreePaneLayout control.
        // The client fragments use the events of the OnstateChangeListener interface to 
        // update the arrows orientation that user can use to redimension the panels
        mMultiPaneControl.addStateObserver(mCategoriesListFragment);
        mMultiPaneControl.addStateObserver(mTasksListFragment);
        mMultiPaneControl.addStateObserver(mTaskDetailFragment);

        mMultiPaneControl.addStateObserver(this);

        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.add(R.id.categoriesList, mCategoriesListFragment, "tag");
        transaction.add(R.id.tasksList, mTasksListFragment);
        transaction.add(R.id.taskDetail, mTaskDetailFragment);
        transaction.commit();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        mScreenOrientation = getResources().getConfiguration().orientation;

        // When device orientationcchange notify the ThreePaneLyout control associated with the activity 
        // to update the distribution of its panels in order to improve usability
        mMultiPaneControl.deviceOrientationHasChange();
    }

    @Override
    public void onCategoriesListSizeControlSelected() {

        if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) {

            VisibilityState visibilityState = mMultiPaneControl.getVisibityState();

            if (visibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE ) {
                mMultiPaneControl.setVisibilityState(VisibilityState.LEFT_VISIBLE);
            } else if ( visibilityState == VisibilityState.LEFT_VISIBLE) {
                mMultiPaneControl.setVisibilityState(VisibilityState.LEFT_AND_MIDDLE_VISIBLE);
            }

        } else { // Configuration.ORIENTATION_PORTRAIT

            // The only possible state if this event is received while the device in 
            // portrait orientation is MIDDLE_VISIBLE
            mMultiPaneControl.setVisibilityState(VisibilityState.MIDDLE_VISIBLE);
        }
    }

    @Override
    public void onTasksListSizeControlSelected(boolean leftControl) {

        VisibilityState visibilityState = mMultiPaneControl.getVisibityState();

        if (leftControl) {

            if ( mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE ) {

                if (visibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE ) {
                    mMultiPaneControl.setVisibilityState(VisibilityState.MIDDLE_VISIBLE);
                } else if (visibilityState == VisibilityState.MIDDLE_VISIBLE ) {
                    mMultiPaneControl.setVisibilityState(VisibilityState.LEFT_AND_MIDDLE_VISIBLE);
                } else if (visibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE ) {
                    mMultiPaneControl.setVisibilityState(VisibilityState.LEFT_AND_MIDDLE_VISIBLE);
                }   

            } else { // Configuration.ORIENTATION_PORTRAIT

                // The only possible state if this event is received while the device in 
                // portrait orientation is LEFT_VISIBLE
                mMultiPaneControl.setVisibilityState(VisibilityState.LEFT_VISIBLE);
            }

        } else {

            if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) {

                if (visibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE) {
                    mMultiPaneControl.setVisibilityState(VisibilityState.MIDDLE_AND_RIGHT_VISIBLE);
                } else if (visibilityState == VisibilityState.MIDDLE_VISIBLE) {
                    mMultiPaneControl.setVisibilityState(VisibilityState.MIDDLE_AND_RIGHT_VISIBLE);
                } else if (visibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE) {
                    mMultiPaneControl.setVisibilityState(VisibilityState.MIDDLE_VISIBLE);
                }   

            } else { // Configuration.ORIENTATION_PORTRAIT

                // The only possible state if this event is received while the device in 
                // portrait orientation is RIGHT_VISIBLE
                mMultiPaneControl.setVisibilityState(VisibilityState.RIGHT_VISIBLE);
            }
        }
    }

    @Override
    public void onDetailTaskSizeControlSelected() {

        VisibilityState visibilityState = mMultiPaneControl.getVisibityState();

        if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) {

            if ( visibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE) {
                mMultiPaneControl.setVisibilityState(VisibilityState.RIGHT_VISIBLE);
            } else if ( visibilityState == VisibilityState.RIGHT_VISIBLE) {
                mMultiPaneControl.setVisibilityState(VisibilityState.MIDDLE_AND_RIGHT_VISIBLE);
            }   

        } else { // Configuration.ORIENTATION_PORTRAIT

            // The only possible state if this event is received while the device in 
            // portrait orientation is MIDDLE_VISIBLE
            mMultiPaneControl.setVisibilityState(VisibilityState.MIDDLE_VISIBLE); 
        }
    }


    @Override
    public void onBeginTransitionState(VisibilityState oldState,
            VisibilityState newState) {
    }

    @Override
    public void onNewStateVisible(VisibilityState newState) { /**/ }
}

ThreePaneLayout.java

/**
 * <p>Control to display up to three panels with a maximum of two simultaneously visible.</p>
 */
public class ThreePaneLayout extends LinearLayout {

    /**
     * Time control takes for the state change animation
     */
    public static final int ANIMATION_DURATION = 300;

    private boolean isScrollingViews;

    /**
     * Possible control visibility states. The states are exclusive, ie, if the control is 
     * in state {@ link LEFT_AND_MIDDLE_VISIBLE} implies that the right pane is not visible.
     */
    public enum VisibilityState {
        LEFT_VISIBLE,
        LEFT_AND_MIDDLE_VISIBLE, 
        MIDDLE_VISIBLE, 
        MIDDLE_AND_RIGHT_VISIBLE,
        RIGHT_VISIBLE
    }

    /**
     * Interface to be implemented by clients that require to be notified
     * when the visibility state change.
     */
    public interface OnStateChangeListener {

        /**
         * Method invoked by the control just prior to the transition state of visibility   
         * 
         * @param oldState   Estado actual de visibilidad control
         * @param newState   Proximo estado de visibilidad del control
         */
        void onBeginTransitionState(VisibilityState oldState, VisibilityState newState);

        /**
         * Method invoked by the control when its visibility status has been updated
         * 
         * @param newState   New visibility state of the control panels
         */
        void onNewStateVisible(VisibilityState newState);

    }

    // Reference to the three panels of the control
    private View mLeftView;
    private View mMiddleView;
    private View mRightView;

    // Variables that store the minimum and maximum widths that can have different panels
    private int mMinPaneWidth = -1;
    private int mMaxPaneWidth;
    private int mFullScreenWidth;

    // Stores the current device orientation
    private int mScreenOrientation;

    // Reference to the current state of the panels
    private VisibilityState mVisibilityState;

    /**
     * Lista de observadores de cambio de estado del control
     */
    private List<OnStateChangeListener> mStateListeners;

    private Handler mHandler = new Handler();

    private Context mContext;

    public ThreePaneLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        Log.i("Log", "Llamado el constructor del control");

        mContext = context;

        mScreenOrientation = getResources().getConfiguration().orientation;

        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {

        setOrientation(HORIZONTAL);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ThreePaneLayout);
        String initialState = a.getString(R.styleable.ThreePaneLayout_initialState);

        if ( initialState != null ) { 
            // The initial state has been defined in the XML

            if (initialState.equals("left_visible")) {
                mVisibilityState = VisibilityState.LEFT_VISIBLE;
            } else if (initialState.equals("left_and_middle_visible")) {
                mVisibilityState = VisibilityState.LEFT_AND_MIDDLE_VISIBLE;
            } 

        } else { 
            // The initial state is not defined in the XML, set the default state

            mVisibilityState = VisibilityState.LEFT_AND_MIDDLE_VISIBLE;
        }
    }

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();

        if ( getChildCount() != 3 ) {
            throw new IllegalStateException("ThreePaneLayout requires defining three daughters views in the XML");
        }

        // Get a reference to the views that make control
        mLeftView   = getChildAt(0);
        mMiddleView = getChildAt(1);
        mRightView  = getChildAt(2);

        configureWidth();
    }

    /**
     * Set the weights of each of the views of the layout container.
     * 
     * If the method takes no arguments recalculates the weights based on the current  visibility 
     * state of the control. If this method receive a parameter is used as visibility state from 
     * which will be held on recalculation
     * 
     * @param args
     */
    private void configureWidth(VisibilityState ... args) {

        LayoutParams leftPaneLayoutParams   = (LayoutParams) mLeftView.getLayoutParams();
        LayoutParams middlePaneLayoutParams = (LayoutParams) mMiddleView.getLayoutParams();
        LayoutParams rightPaneLayoutParams  = (LayoutParams) mRightView.getLayoutParams();

        VisibilityState visibilityState = args.length == 0 ? mVisibilityState : args[0];

        if (args.length > 0) {

            leftPaneLayoutParams.width   = 0;
            middlePaneLayoutParams.width = 0;
            rightPaneLayoutParams.width  = 0;
        }

        if ( visibilityState == VisibilityState.LEFT_VISIBLE ) {

            leftPaneLayoutParams.weight   = 1.0f; 
            middlePaneLayoutParams.weight = 0.0f; 
            rightPaneLayoutParams.weight  = 0.0f; 

        } else if ( visibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE ) {

            leftPaneLayoutParams.weight   = 0.35f;
            middlePaneLayoutParams.weight = 0.65f;
            rightPaneLayoutParams.weight  = 0.0f; 

        } else if ( visibilityState == VisibilityState.MIDDLE_VISIBLE ) {

            leftPaneLayoutParams.weight   = 0.0f; 
            middlePaneLayoutParams.weight = 1.0f;
            rightPaneLayoutParams.weight  = 0.0f;

        } else if ( visibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE ) {

            leftPaneLayoutParams.weight   = 0.0f;
            middlePaneLayoutParams.weight = 0.35f;
            rightPaneLayoutParams.weight  = 0.65f;

        } else if ( visibilityState == VisibilityState.RIGHT_VISIBLE ) {

            leftPaneLayoutParams.weight   = 0.0f;
            middlePaneLayoutParams.weight = 0.0f;
            rightPaneLayoutParams.weight  = 1.0f;
        }

        // Refresh the view and compute the size of the view in the screen. 
        requestLayout();
    }

    /**
     * Method that performs the visibility state transition control (redistribution of the panels)
     * 
     * @param newVisibilityState   New visibility state required.
     * @param resetDimensions      This parameter is optional and should be used only when you are performing a 
     *                             state transcion due to a change of device orientation so we can recalculated 
     *                             weights and widths of the panels.
     */
    public void setVisibilityState(VisibilityState newVisibilityState, boolean ... resetDimensions) {

        // Ignore the request if the control is being resized or if the requested state is equal to the current
        if ( isScrollingViews || newVisibilityState == mVisibilityState ) {
            return;
        }

        // If requested any state that contains more than one panel and device orientation is portrait, 
        // ignore the request (this control only supports multiple panels visible in landscape)
        if (mScreenOrientation == Configuration.ORIENTATION_PORTRAIT) {
            if ( newVisibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE || 
                 newVisibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE ) {
                return;
            }
        }

        if (resetDimensions.length > 0 && resetDimensions[0] == true) {

            configureWidth(newVisibilityState);
            mMinPaneWidth = -1;
        }

        // Calculate the maximum and minimum widths of the control panel if the have not been defined
        if (mMinPaneWidth == -1) {

            DisplayMetrics displayMetrics = new DisplayMetrics();
            WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
            wm.getDefaultDisplay().getMetrics(displayMetrics);
            int screenWidth = displayMetrics.widthPixels;

            if ( mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE ) {

                mMinPaneWidth    = (int) (screenWidth * 0.35);
                mMaxPaneWidth    = screenWidth - mMinPaneWidth;
                mFullScreenWidth = screenWidth;

            } else { // Configuration.ORIENTATION_PORTRAIT

                mMinPaneWidth = mMaxPaneWidth = mFullScreenWidth = screenWidth;
            }

            resetWidget(mLeftView, mMinPaneWidth); 
            resetWidget(mMiddleView, mMaxPaneWidth);
            resetWidget(mRightView, mMaxPaneWidth);

            requestLayout();
        }

        isScrollingViews = true;
        mHandler.postDelayed(new Runnable() {

            @Override
            public void run() {
                isScrollingViews = false;
            }
        }, ANIMATION_DURATION + 100);


        VisibilityState currentVisibilityState = mVisibilityState;

        // Notify control observers will produce a state transition 
        if ( mStateListeners != null ) {
            for ( OnStateChangeListener observer : mStateListeners ) {
                observer.onBeginTransitionState(currentVisibilityState, newVisibilityState);
            }
        }

        if (resetDimensions.length == 0) {
            // Perform the movement of the panels to match the new state required
            animateVisibilityStateTransition(currentVisibilityState, newVisibilityState);           
        }

        // Update the reference to the current state
        mVisibilityState = newVisibilityState;

        // Notify the new control state to the control's observers 
        if ( mStateListeners != null ) {
            for ( OnStateChangeListener observer : mStateListeners ) {
                observer.onNewStateVisible(mVisibilityState);
            }
        }
    }

    /**
     * Moves on the x axis and resize the panels to suit new visibility state required.
     * 
     * @param currentVisibilityState    Current state control visibility
     * @param requiredVisibilityState   New visibility state required
     */
    private void animateVisibilityStateTransition(VisibilityState currentVisibilityState, 
            VisibilityState requiredVisibilityState) {

        switch (requiredVisibilityState) {

        case LEFT_VISIBLE:

            if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) {

                if (currentVisibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE) {

                    ObjectAnimator.ofInt(this, "leftWidth", mMinPaneWidth, mFullScreenWidth)
                            .setDuration(ANIMATION_DURATION).start();
                }

            } else { // Configuration.ORIENTATION_PORTRAIT

                if (currentVisibilityState == VisibilityState.MIDDLE_VISIBLE) {

                    translateView(mMaxPaneWidth, mLeftView, mMiddleView, mRightView);

                } else if (currentVisibilityState == VisibilityState.RIGHT_VISIBLE) {

                    translateView(2 * mMaxPaneWidth, mLeftView, mMiddleView, mRightView);
                }
            } 

            break;

        case LEFT_AND_MIDDLE_VISIBLE:
            // Este estado solo es posible en orientacion panoramica

            if (currentVisibilityState == VisibilityState.MIDDLE_VISIBLE) {

                translateView(mMinPaneWidth, mLeftView, mMiddleView, mRightView);

                ObjectAnimator.ofInt(this, "middleWidth", mFullScreenWidth, mMaxPaneWidth)
                        .setDuration(ANIMATION_DURATION).start();

            } else if (currentVisibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE) {

                translateView(mMinPaneWidth, mLeftView, mMiddleView, mRightView);

                ObjectAnimator.ofInt(this, "middleWidth", mMinPaneWidth, mMaxPaneWidth)
                        .setDuration(ANIMATION_DURATION).start();

            } else if (currentVisibilityState == VisibilityState.LEFT_VISIBLE) {

                ObjectAnimator.ofInt(this, "leftWidth", mFullScreenWidth, mMinPaneWidth)
                        .setDuration(ANIMATION_DURATION).start();
            }

            break;

        case MIDDLE_VISIBLE:

            if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) { 

                if (currentVisibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE) {

                    translateView(-1 * mMinPaneWidth, mLeftView, mMiddleView, mRightView);

                    ObjectAnimator.ofInt(this, "middleWidth", mMaxPaneWidth, mFullScreenWidth)
                            .setDuration(ANIMATION_DURATION).start();

                } else if (currentVisibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE) {

                    ObjectAnimator.ofInt(this, "middleWidth", mMinPaneWidth, mFullScreenWidth)
                            .setDuration(ANIMATION_DURATION).start();
                }

            } else { // Configuration.ORIENTATION_PORTRAIT

                if (currentVisibilityState == VisibilityState.LEFT_VISIBLE) {

                    translateView(-1 * mMaxPaneWidth, mLeftView, mMiddleView, mRightView);

                } else if (currentVisibilityState == VisibilityState.RIGHT_VISIBLE) {

                    translateView(mMaxPaneWidth, mLeftView, mMiddleView, mRightView);
                }

            }

            break;

        case MIDDLE_AND_RIGHT_VISIBLE:
            // Este estado solo es posible en orientacion panoramica

            if (currentVisibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE) {

                translateView(-1 * mMinPaneWidth, mLeftView, mMiddleView, mRightView);

                ObjectAnimator.ofInt(this, "middleWidth", mMaxPaneWidth, mMinPaneWidth)
                        .setDuration(ANIMATION_DURATION).start();

            } else if (currentVisibilityState == VisibilityState.MIDDLE_VISIBLE) {

                ObjectAnimator.ofInt(this, "middleWidth", mFullScreenWidth, mMinPaneWidth)
                        .setDuration(ANIMATION_DURATION).start();


            } else if (currentVisibilityState == VisibilityState.RIGHT_VISIBLE) {

                translateView(mMinPaneWidth, mLeftView, mMiddleView, mRightView);

                ObjectAnimator.ofInt(this, "rightWidth", mFullScreenWidth, mMaxPaneWidth)
                        .setDuration(ANIMATION_DURATION).start();
            }

            break;

        case RIGHT_VISIBLE:

            if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) { 

                if (currentVisibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE) {

                    translateView(-1 * mMinPaneWidth, mLeftView, mMiddleView, mRightView);

                    ObjectAnimator.ofInt(this, "rightWidth", mMaxPaneWidth, mFullScreenWidth)
                            .setDuration(ANIMATION_DURATION).start();
                }

            } else { // Configuration.ORIENTATION_PORTRAIT

                if (currentVisibilityState == VisibilityState.LEFT_VISIBLE) {

                    translateView(-2 * mMaxPaneWidth, mLeftView, mMiddleView, mRightView);

                } else if (currentVisibilityState == VisibilityState.MIDDLE_VISIBLE) {

                    translateView(-1 * mMaxPaneWidth, mLeftView, mMiddleView, mRightView);
                }
            }

            break;
        }
    }

    public VisibilityState getVisibityState() {
        return mVisibilityState;
    }

    @SuppressWarnings("unused")
    private void setLeftWidth(int value) {
        mLeftView.getLayoutParams().width = value;
        requestLayout();
    }

    @SuppressWarnings("unused")
    private void setMiddleWidth(int value) {
        mMiddleView.getLayoutParams().width = value;
        requestLayout();
    }

    @SuppressWarnings("unused")
    private void setRightWidth(int value) {
        mRightView.getLayoutParams().width = value;
        requestLayout();
    }

    /**
     * Moves in the X axis the views received as parameter.
     *   
     * @param deltaX   Number of pixels that are shifted in the x-axis views
     * @param views    Views on which it will move
     */
    private void translateView(int deltaX, View... views) {

        for (final View view : views) {

            view.setLayerType(View.LAYER_TYPE_NONE, null);

            view.animate().translationXBy(deltaX).setDuration(ANIMATION_DURATION)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            view.setLayerType(View.LAYER_TYPE_NONE, null);
                        }
                    });
        }
    }

    /**
     * Updates the properties of length and weight on the layout of the view passed as parameter 
     * 
     * @param view    Vista on which perform the update of the properties
     * @param width   New width
     */
    private void resetWidget(View view, int width) {

        LinearLayout.LayoutParams p = (LinearLayout.LayoutParams) view.getLayoutParams();
        p.width = width;
        p.weight = 0;
    }

    /**
     * Adds the component passed as a parameter to the list of control observers. The observers are notified
     * every time the control change the panels distribution. Observers also receive a notification just before 
     * starting the transition state by the control.
     * 
     * @param observer   component that implements the {@ link OnStateChangeListener} interface
     *                   to recieve notifications when the visibility control state change
     */
    public void addStateObserver(OnStateChangeListener observer) {

        if ( mStateListeners == null ) {
            mStateListeners = new ArrayList<OnStateChangeListener>();
        }

        mStateListeners.add(observer);
    }

    /**
     * Removes the component passed as parameter from the list of observers of 
     * state change. Observers are added to the list through the method {@ link # addStateObserver}
     * 
     * @param observer   component that implements the {@ link OnStateChangeListener} interface
     *                   to recieve notifications when the visibility control state change
     */
    public void deleteStatetObserver(OnStateChangeListener observer) {

        if ( mStateListeners == null ) return;

        mStateListeners.remove(observer);
    }


    /**
     * Method invoked by the host activity when the orientation of the device has changed. Based on the 
     * new orientation the control redistributes panels to match the new orientation and improve usability
     */
    public void deviceOrientationHasChange() 
    {
        int newScreenOrientation = getResources().getConfiguration().orientation;

        VisibilityState currentVisibilityState = getVisibityState();
        VisibilityState newVisibilityState = null;

        if (newScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) {
            // When orientation chamge to landscape the only possible states in the previous orientation 
            // (portrait) can only be those where not coexist multiple views (eg LEFT_VISIBLE, 
            // MIDDLE_VISIBLE, RIGHT_VISIBLE)

            if (currentVisibilityState == VisibilityState.LEFT_VISIBLE) {
                newVisibilityState = VisibilityState.LEFT_AND_MIDDLE_VISIBLE;
            } else if (currentVisibilityState == VisibilityState.MIDDLE_VISIBLE) {
                newVisibilityState = VisibilityState.MIDDLE_VISIBLE;
            } else if (currentVisibilityState == VisibilityState.RIGHT_VISIBLE) {
                newVisibilityState = VisibilityState.RIGHT_VISIBLE;
            }

        } else { // Configuration.ORIENTATION_PORTRAIT

            if (currentVisibilityState == VisibilityState.LEFT_VISIBLE) {
                newVisibilityState = VisibilityState.LEFT_VISIBLE;
            } else if ( currentVisibilityState == VisibilityState.LEFT_AND_MIDDLE_VISIBLE || 
                        currentVisibilityState == VisibilityState.MIDDLE_VISIBLE ) {
                newVisibilityState = VisibilityState.MIDDLE_VISIBLE;
            } else if (currentVisibilityState == VisibilityState.MIDDLE_AND_RIGHT_VISIBLE) {
                newVisibilityState = VisibilityState.RIGHT_VISIBLE;
            } else if (currentVisibilityState == VisibilityState.RIGHT_VISIBLE) {
                newVisibilityState = VisibilityState.RIGHT_VISIBLE;
            }
        }

        mScreenOrientation = newScreenOrientation;

        mMinPaneWidth = -1;
        configureWidth(newVisibilityState);

        mVisibilityState = newVisibilityState;
    }

    public View getLeftView() {
        return mLeftView;
    }

    public View getMiddleView() {
        return mMiddleView;
    }

    public View getRightView() {
        return mRightView;
    }

}

例如,当设备处于横向且可见性状态为 MIDDLE AND RIGHT(参见图 1)时,当您将设备旋转为纵向时,状态更改将失败(参见图 2)。

在此处输入图像描述

图1

在此处输入图像描述

图 2

为了对应用程序进行更详细的分析,我在 github 上发布了一个使用该控件的示例应用程序,可从以下链接下载:https ://github.com/dfpalomar/ThreePaneLayout

我尝试使用 methods和控件的 configureWidth 方法强制重绘视图,但没有得到预期的结果requestLayoutinvalidateforceLayout

欢迎任何关于我如何解决问题的建议:D

4

1 回答 1

0

更改屏幕旋转时没有自动保持会话的功能,您需要自己手动执行此操作,因为正在重新加载活动。您可以在此处阅读详细信息:http: //developer.android.com/guide/topics/manifest/activity-element.html#config

StackOverflow上也有很多类似的问题,所以也请尝试搜索这个以获得合适的答案。

于 2013-08-27T13:54:38.270 回答