Side Menu侧边栏动画效果

前几天在github上看到一个DrawableLayout的项目,地址:https://github.com/Yalantis/Side-Menu.Android,感觉效果很不错,以后可以用到自己的项目中,于是对项目进行了仿写,并没有使用DrawableLayout,而是自己定义了一个LinearLayout,向其中添加按钮,点击按钮后进行页面的切换,具体效果如下所示:
Side Menu侧边栏动画效果_第1张图片
看结果还是挺不错的,以下是源码分析,在编写过程中,借鉴了github上面的代码。

1、动画效果
在侧边栏弹出的时候,我们看到了一个翻转的动画效果,以y轴为翻转轴,菜单依次翻转弹出,我们需要定义一个FlipAnimation,继承Animation,实现翻转效果,代码如下:

/**
 * 3d变化动画,实现了View绕Y轴旋转的效果,来源于开源控件Yalantis/Side-Menu.Android
 * 地址 https://github.com/Yalantis/Side-Menu.Android
 * Created by Konstantin on 22.12.2014.
 */
public class FlipAnimation extends Animation {
    private final float mFromDegrees;
    private final float mToDegrees;
    private final float mCenterX;
    private final float mCenterY;
    private Camera mCamera;

    public FlipAnimation(float fromDegrees, float toDegrees, float centerX, float centerY) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;
        mCenterX = centerX;
        mCenterY = centerY;
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float fromDegrees = mFromDegrees;
        float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

        final float centerX = mCenterX;
        final float centerY = mCenterY;
        final Camera camera = mCamera;

        final Matrix matrix = t.getMatrix();

        camera.save();

        camera.rotateY(degrees);

        camera.getMatrix(matrix);
        camera.restore();

        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);

    }

}

主要就是通过矩阵变换,实现动画效果,改变这个类,我们可以实现自定义动画效果。

2、侧边菜单动画效果
有了动画效果后,需要将动画效果运用在侧边菜单上,定义ViewAnimator,代码如下:

/**
 * View动画
 * Created by dingxiaolei on 16/4/1.
 */
public class ViewAnimator {
    private final int ANIMATION_DURATION = 175;

    private Activity activity;
    private List list = new ArrayList<>();
    private List viewList = new ArrayList<>();
    private ViewAnimatorListener animatorListener;

    public ViewAnimator(Activity activity, List list, ViewAnimatorListener animatorListener) {
        this.activity = activity;
        this.list = list;
        this.animatorListener = animatorListener;
    }

    public void showMenuContent() {
        setViewsClickable(true);
        viewList.clear();
        animatorListener.showMenu();

        final int size = list.size();
        for (int i = 0; i < size; i++) {
            String menuItemName = list.get(i).getItemName();
            int menuItemImgRes = list.get(i).getImageRes();

            View viewMenu = activity.getLayoutInflater().inflate(R.layout.menu_list_item, null);
            viewMenu.setVisibility(View.GONE);
            TextView textView = (TextView) viewMenu.findViewById(R.id.menu_item_text);
            ImageView imageView = (ImageView) viewMenu.findViewById(R.id.menu_item_image);
            textView.setText(menuItemName);
            imageView.setBackgroundResource(menuItemImgRes);

            final int finalI = i;
            viewMenu.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (finalI == size - 1) {
                        hideMenuContent();
                    } else {
                        animatorListener.onSwitch(finalI);
                    }
                }
            });
            viewList.add(viewMenu);
            animatorListener.addViewToContainer(viewMenu);

            final double position = i;
            final double delay = 3 * ANIMATION_DURATION * (position / size);
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    animateView(finalI);
                }
            }, (long) delay);
        }
    }

    private void animateView(int position) {
        View view = viewList.get(position);
        view.setVisibility(View.VISIBLE);
        FlipAnimation flipAnimation = new FlipAnimation(90, 0, 0.0f, view.getHeight() / 2.0f);
        flipAnimation.setDuration(ANIMATION_DURATION);
        flipAnimation.setFillAfter(true);

        view.startAnimation(flipAnimation);
    }

    private void hideMenuContent() {
        setViewsClickable(false);
        int size = list.size();
        for (int i = 0; i < size; i++) {
            final double position = i;
            final double delay = 3 * ANIMATION_DURATION * (position / size);
            new Handler().postDelayed(new Runnable() {
                public void run() {
                    animateHideView((int) position);
                }
            }, (long) delay);
        }
    }

    private void animateHideView(int position) {
        View view = viewList.get(position);
        view.setVisibility(View.VISIBLE);
        FlipAnimation flipAnimation = new FlipAnimation(0, 90, 0.0f, view.getHeight() / 2.0f);
        flipAnimation.setDuration(ANIMATION_DURATION);
        flipAnimation.setFillAfter(true);

        if (position == viewList.size() - 1) {
            animatorListener.hideMenu();
        }

        view.startAnimation(flipAnimation);
    }

    private void setViewsClickable(boolean clickable) {
        for (View view : viewList) {
            view.setEnabled(clickable);
        }
    }

    public interface ViewAnimatorListener {

        public void onSwitch(int position);

        public void addViewToContainer(View view);

        public void showMenu();

        public void hideMenu();
    }
}

其中showMenuContent是显示菜单函数,hideMenuContent是隐藏菜单函数,通过Handler().postDelayed,来进行动画的延时显示。在这个类中,我们定义了一个内部接口ViewAnimatorListener,当这个函数被调用时,可以通过接口实现一些效果,这点可以在MainActivity中看出。

3、定义菜单每一项的数据结构
就是一张图片一个文字,没啥说的,代码如下

/**
 * 侧滑菜单Item
 * Created by dingxiaolei on 16/4/1.
 */
public class MenuItemBean {
    private String itemName;
    private int imageRes;

    public MenuItemBean() {
    }

    public MenuItemBean(String itemName, int imageRes) {
        this.itemName = itemName;
        this.imageRes = imageRes;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public int getImageRes() {
        return imageRes;
    }

    public void setImageRes(int imageRes) {
        this.imageRes = imageRes;
    }
}

4、定义Fragment
在点击侧边菜单每一项的时候,会进行页面切换,只要替换其中的fragment即可,这里我就定义了一个fragment,中间一个textview,fragment代码如下

public class ContentFragment extends android.support.v4.app.Fragment{

    private RelativeLayout relativeLayout;
    private TextView textView;

    private int res;
    private List list = new ArrayList<>();

    public static ContentFragment newInstance(int resId) {
        ContentFragment contentFragment = new ContentFragment();
        Bundle bundle = new Bundle();
        bundle.putInt(Integer.class.getName(), resId);
        contentFragment.setArguments(bundle);
        return contentFragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_content, container, false);
        relativeLayout = (RelativeLayout) view.findViewById(R.id.content);
        textView = (TextView) view.findViewById(R.id.text);

        relativeLayout.setBackgroundResource(list.get(res).getImageRes());
        textView.setText(list.get(res).getItemName());
        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        res = getArguments().getInt(Integer.class.getName(), 0);
        initData();
    }

    private void initData() {
        String[] menuItemNameList = {"姓名", "性别", "年龄", "籍贯", "配偶", "学历"};
        MenuItemBean menuItem0 = new MenuItemBean(menuItemNameList[0], R.color.red);
        list.add(menuItem0);
        MenuItemBean menuItem1 = new MenuItemBean(menuItemNameList[1], R.color.green);
        list.add(menuItem1);
        MenuItemBean menuItem2 = new MenuItemBean(menuItemNameList[2], R.color.blue);
        list.add(menuItem2);
        MenuItemBean menuItem3 = new MenuItemBean(menuItemNameList[3], R.color.yellow);
        list.add(menuItem3);
        MenuItemBean menuItem4 = new MenuItemBean(menuItemNameList[4], R.color.lightBlue);
        list.add(menuItem4);
        MenuItemBean menuItem5 = new MenuItemBean(menuItemNameList[5], R.color.pink);
        list.add(menuItem5);
    }
}

5、MainActivity
最后是在主页面中,添加侧边菜单,这样达到了可以复用的效果,同时实现ViewAnimator中所有的接口方法,达到我们自己所想要的效果。代码如下:

public class MainActivity extends AppCompatActivity implements ViewAnimator.ViewAnimatorListener {

    private ViewAnimator viewAnimator;
    private LinearLayout linearLayout;
    private ScrollView scrollView;
    private ImageView showMenuImageView;

    private ContentFragment contentFragment;

    private List list = new ArrayList<>();

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

        contentFragment = ContentFragment.newInstance(0);
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fram_content, contentFragment)
                .commit();

        createMenuList();

        linearLayout = (LinearLayout) findViewById(R.id.left_drawer);
        showMenuImageView = (ImageView) findViewById(R.id.show_slide_menu);
        scrollView = (ScrollView) findViewById(R.id.scrollView);
        viewAnimator = new ViewAnimator(this, list, this);

        showMenuImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//              showMenuImageView.setVisibility(View.GONE);
                viewAnimator.showMenuContent();
            }
        });
    }

    private void createMenuList() {
        String[] menuItemNameList = {"姓名", "性别", "年龄", "籍贯", "配偶", "学历", "隐藏"};
        MenuItemBean menuItem0 = new MenuItemBean(menuItemNameList[0], R.drawable.ic_apps_grey600_24dp);
        list.add(menuItem0);
        MenuItemBean menuItem1 = new MenuItemBean(menuItemNameList[1], R.drawable.ic_arrow_drop_down_circle_grey600_24dp);
        list.add(menuItem1);
        MenuItemBean menuItem2 = new MenuItemBean(menuItemNameList[2], R.drawable.ic_airplanemode_on_grey600_24dp);
        list.add(menuItem2);
        MenuItemBean menuItem3 = new MenuItemBean(menuItemNameList[3], R.drawable.ic_dvr_grey600_24dp);
        list.add(menuItem3);
        MenuItemBean menuItem4 = new MenuItemBean(menuItemNameList[4], R.drawable.ic_check_grey600_24dp);
        list.add(menuItem4);
        MenuItemBean menuItem5 = new MenuItemBean(menuItemNameList[5], R.drawable.ic_access_alarm_grey600_24dp);
        list.add(menuItem5);
        MenuItemBean menuItem6 = new MenuItemBean(menuItemNameList[6], R.drawable.ic_close_grey600_24dp);
        list.add(menuItem6);
    }

    @Override
    public void onSwitch(int position) {
        replaceFragment(position);
    }

    private void replaceFragment(int position) {
        ContentFragment contentFragment = ContentFragment.newInstance(position);
        getSupportFragmentManager().beginTransaction().replace(R.id.fram_content, contentFragment).commit();
    }

    @Override
    public void addViewToContainer(View view) {
        linearLayout.addView(view);
    }

    @Override
    public void showMenu() {
        scrollView.setVisibility(View.VISIBLE);
        showMenuImageView.setVisibility(View.GONE);
    }

    @Override
    public void hideMenu() {
        scrollView.setVisibility(View.GONE);
        linearLayout.removeAllViews();
        showMenuImageView.setVisibility(View.VISIBLE);
    }
}

项目源码下载:http://download.csdn.net/detail/ddxxll2008/9487997

你可能感兴趣的:(安卓开发)