Side Menu侧边栏动画效果
2016-04-11 22:37
363 查看
前几天在github上看到一个DrawableLayout的项目,地址:https://github.com/Yalantis/Side-Menu.Android,感觉效果很不错,以后可以用到自己的项目中,于是对项目进行了仿写,并没有使用DrawableLayout,而是自己定义了一个LinearLayout,向其中添加按钮,点击按钮后进行页面的切换,具体效果如下所示:
看结果还是挺不错的,以下是源码分析,在编写过程中,借鉴了github上面的代码。
1、动画效果
在侧边栏弹出的时候,我们看到了一个翻转的动画效果,以y轴为翻转轴,菜单依次翻转弹出,我们需要定义一个FlipAnimation,继承Animation,实现翻转效果,代码如下:
主要就是通过矩阵变换,实现动画效果,改变这个类,我们可以实现自定义动画效果。
2、侧边菜单动画效果
有了动画效果后,需要将动画效果运用在侧边菜单上,定义ViewAnimator,代码如下:
其中showMenuContent是显示菜单函数,hideMenuContent是隐藏菜单函数,通过Handler().postDelayed,来进行动画的延时显示。在这个类中,我们定义了一个内部接口ViewAnimatorListener,当这个函数被调用时,可以通过接口实现一些效果,这点可以在MainActivity中看出。
3、定义菜单每一项的数据结构
就是一张图片一个文字,没啥说的,代码如下
4、定义Fragment
在点击侧边菜单每一项的时候,会进行页面切换,只要替换其中的fragment即可,这里我就定义了一个fragment,中间一个textview,fragment代码如下
5、MainActivity
最后是在主页面中,添加侧边菜单,这样达到了可以复用的效果,同时实现ViewAnimator中所有的接口方法,达到我们自己所想要的效果。代码如下:
项目源码下载:http://download.csdn.net/detail/ddxxll2008/9487997
看结果还是挺不错的,以下是源码分析,在编写过程中,借鉴了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<MenuItemBean> list = new ArrayList<>(); private List<View> viewList = new ArrayList<>(); private ViewAnimatorListener animatorListener; public ViewAnimator(Activity activity, List<MenuItemBean> 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<MenuItemBean> 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<MenuItemBean> 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
相关文章推荐
- Gifski:一个跨平台的高质量 GIF 编码器
- 模仿动画的放大缩小容器
- jQuery 1.9.1源码分析系列(十五)动画处理之缓动动画核心Tween
- Android实现定制返回按钮动画效果的方法
- Android中ViewFlipper的使用及设置动画效果实例详解
- jQuery实现美观的多级动画效果菜单代码
- php判断GIF图片是否为动画的方法
- jQuery实现动画效果circle实例
- HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
- 浅析JavaScript动画
- js排序动画模拟-插入排序
- javascript+HTML5的Canvas实现Lab单车动画效果
- 基于javascript实现漂亮的页面过渡动画效果附源码下载
- js实现按钮颜色渐变动画效果
- 超赞的jQuery图片滑块动画特效代码汇总
- jQuery实现连续动画效果实例分析
- 利用jquery制作滚动到指定位置触发动画
- jQuery实现的给图片点赞+1动画效果(附在线演示及demo源码下载)
- jQuery实现带有洗牌效果的动画分页实例
- jQuery动画效果相关方法实例分析