0

您一定使用过 facebook android 应用程序。我想实现与 facebook 使用相同的导航:向左滑动菜单打开,向右滑动显示聊天列表。在中间,活动和布局不断变化。但我很困惑如何进行这样的导航。(最值得注意的是,当向左或向右滑动时,中间页面显示一半。)帮助?

4

2 回答 2

1

你有两个不错的选择。

  1. 导航抽屉:http: //developer.android.com/design/patterns/navigation-drawer.html
  2. 滑动抽屉:https ://github.com/jfeinstein10/SlidingMenu

您可以为您的用例制作多个导航抽屉。

于 2013-10-24T11:20:23.157 回答
1

我在一小时前安装了 FB 应用程序。当您点击主要内容右上角的图标时,主要内容会向左移动以显示右侧的内容。在移动过程中,显示​​的内容保持固定并位于主要内容之后。

我根据上面的分析写了这个轻量级的抽象:

package org.yourdomain.app;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;

abstract public class NavigatorActivity extends Activity {
    static public final String TAG = "NavigatorActivity";
    static public final Boolean DEBUG_LIFECYCLE = false;

    /**
     * True when menu is on and vice versa
     */
    private boolean mToggled;
    /**
     * Percentage of the main content to keep shown
     */
    private float mDistance;
    /**
     * Navigator listener
     */
    private NavigatorListener mListener;
    /**
     * Content view
     */
    private ViewGroup mContentLayout;
    /**
     * Menu frame
     */
    private FrameLayout mMenuLayout;
    /**
     * Main frame
     */
    private FrameLayout mMainLayout;
    /**
     * Speed of toggle animation
     */
    private long mSpeed;
    /**
     * Width of the content view
     */
    private int mContentWidth;
    /**
     * Height of the content view
     */
    private int mContentHeight;
    /**
     * The current distance to slide the main frame
     */
    private int mToggleDistance;

    /**
     *
     */
    public NavigatorActivity() {
        mToggled = false;
        mDistance = 80;
        mSpeed = 300l;
    }

    /**
     * Speed setter.
     *
     * Controls how fast the menu frame is revealed.
     *
     * @param speed
     */
    public void setSpeed(long speed) {
        mSpeed = speed;
    }

    /**
     * Distance setter.
     *
     * The distance is the % of the oriented screen to pull the main frame in order to reveal the
     * menu frame.
     *
     * @param distance
     */
    public void setDistance(float distance) {
        mDistance = distance;
    }

    /**
     * Navigator listener setter.
     *
     * @param listener
     */
    public void setNavigatorListener(NavigatorListener listener) {
        mListener = listener;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (DEBUG_LIFECYCLE) Log.v(TAG, "onCreate " + this + ": " + savedInstanceState);
        initContentLayout();
        setContentView(mContentLayout);
        initMenuLayout();
        mContentLayout.addView(mMenuLayout);
        initMainLayout();
        mContentLayout.addView(mMainLayout);
    }

    /**
     * Initializes the main frame.
     */
    private void initMainLayout() {
        int hw = RelativeLayout.LayoutParams.MATCH_PARENT;
        mMainLayout = new FrameLayout(this) {
            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                setMeasuredDimension(mContentWidth, mContentHeight);
            }
        };
        RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(hw, hw);
        p.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        p.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        mMainLayout.setLayoutParams(p);
    }

    /**
     * Initializes the menu frame.
     */
    private void initMenuLayout() {
        int hw = RelativeLayout.LayoutParams.MATCH_PARENT;
        mMenuLayout = new FrameLayout(this);
        RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(hw, hw);
        p.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        p.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        mMenuLayout.setLayoutParams(p);
    }

    /**
     * Initialize the activity's content layout.
     */
    private void initContentLayout() {
        final int hw = RelativeLayout.LayoutParams.MATCH_PARENT;
        mContentLayout = new RelativeLayout(this) {
            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                mContentWidth = MeasureSpec.getSize(widthMeasureSpec);
                mContentHeight = MeasureSpec.getSize(heightMeasureSpec);
                setMeasuredDimension(mContentWidth, mContentHeight);
                mToggleDistance = Math.round((mDistance / 100f) * (float) mContentWidth);
            }
        };
        mContentLayout.setLayoutParams(new RelativeLayout.LayoutParams(hw, hw));
    }

    /**
     * Inflates two project XML layout and adds them to the menu and main layout frames.
     *
     * @param menuLayoutResId
     * @param mainLayoutResId
     */
    protected void setContentViews(int menuLayoutResId, int mainLayoutResId) {
        final LayoutInflater inflater = getLayoutInflater();
        inflater.inflate(menuLayoutResId, mMenuLayout);
        inflater.inflate(mainLayoutResId, mMainLayout);
    }

    /**
     * Toggle the menu frame.
     */
    final public void toggleNavigator() {
        final boolean isToggled = mToggled = !mToggled;
        if (DEBUG_LIFECYCLE) Log.v(TAG, "toggleNavigatorMenu " + this);
        RelativeLayout.LayoutParams menuParams = (RelativeLayout.LayoutParams) mMenuLayout.getLayoutParams();
        menuParams.setMargins(mContentWidth - mToggleDistance, 0, 0, 0);
        final RelativeLayout.LayoutParams mainParams = (RelativeLayout.LayoutParams) mMainLayout.getLayoutParams();
        ValueAnimator animator = ValueAnimator.ofInt(mainParams.leftMargin, mToggled ? -mToggleDistance : 0);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mainParams.leftMargin = (Integer) valueAnimator.getAnimatedValue();
                mMainLayout.requestLayout();
            }
        });
        animator.addListener(new Animator.AnimatorListener() {

            @Override
            public void onAnimationStart(Animator animation) {}

            @Override
            public void onAnimationEnd(Animator animation) {
                if (mListener != null) {
                    mListener.onNavigatorToggled(isToggled);
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {}

            @Override
            public void onAnimationRepeat(Animator animation) {}
        });
        animator.setDuration(mSpeed);
        animator.start();
    }

    public static interface NavigatorListener {
        public void onNavigatorToggled(boolean isToggled);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            toggleNavigator();
        }
        return super.onKeyUp(keyCode, event);
    }
}

示例用法:

package org.yourdomain.project;

import android.os.Bundle;
import org.yourdomain.app.NavigatorActivity;

public class YourActivity extends NavigatorActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setDistance(80); // will leave 20% of the main content in view
        setNavigatorListener(new NavigatorListener() {
            @Override
            public void onNavigatorToggled(boolean isToggled) {
                // Load content dynamically, like FB does?
            }
        });
        setContentViews(R.layout.layout_menu, R.layout.activity_your);
    }
}
  • compileSdkVersion 20
  • minSdkVersion 16
  • targetSdkVersion 20

单击 Android 设备上的物理菜单按钮将切换导航器。

我计划在我自己的几个启动项目中使用它。

如果您有任何问题,请告诉我。我希望这可以帮助你。

于 2014-07-23T10:07:19.933 回答