来自:http://blog.csdn.net/ywl5320/article/details/50807680
先看效果图:(文章结尾有Demo下载地址)
最近在做一个电商平台的应用,里面有一个效果就是在商品列表上层有一个圆形菜单,在列表滑动时菜单会收缩滑动停止时会展开。刚看到这个效果时感觉不好实现,首先是这个半圆,然后还会收缩变小,但是当我们把这个菜单拆分开来后就很好理解了:
1、首先是菜单背景那个圆,其实就是一个实体圆,只是向右偏离了一段距离,所以就呈现了半圆的效果;
2、然后是收缩效果,其实也不难,只是位移动画和缩放动画的合用而已,在大小缩放的同时再向左便宜就可以了;
3、然后就是里面的菜单项,也是用了位移,缩放和透明度的动画合集实现的。
原理就是这样的,只是具体位移多少,缩放多少就看自己的需求然后进行测试了。这里用到了View.animate().(...)属性动画。这个动画很简单也很实用,只是在3.0以后才有的,不过现在大多数都是基于4.0开发的APP,所以这个属性动画可以放心的用的。
现在看看实现步骤:
一、首先是绘制菜单背景圆:
- <?xml version="1.0" encoding="utf-8"?>
- <shape
- xmlns:android= "http://schemas.android.com/apk/res/android"
- android:shape= "oval"
- android:useLevel= "false" >
- <solid android:color= "#FF4081" />
- </shape>
这里用shape就可以绘制一个实心圆了,不用使用图片。
二、菜单布局:
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="${relativePackage}.${activityClass}" >
- <ListView
- android:id="@+id/listview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- </ListView>
- <RelativeLayout
- android:id="@+id/rl_circle_menu"
- android:layout_width="162dp"
- android:layout_height="162dp"
- android:clickable="true"
- android:background="@drawable/circle_drawable"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
- android:layout_marginBottom="24dp"
- android:layout_marginRight="-92dp">
- <ImageView
- android:id="@+id/iv_show"
- android:layout_width="26dp"
- android:layout_height="34dp"
- android:src="@drawable/icon_show"
- android:layout_centerVertical="true"
- android:layout_marginLeft="8dp"/>
- <ImageView
- android:id="@+id/iv_home"
- android:layout_width="26dp"
- android:layout_height="34dp"
- android:src="@drawable/icon_homepage"
- android:layout_toRightOf="@+id/iv_show"
- android:layout_above="@+id/iv_show"
- android:layout_marginBottom="4dp"/>
-
- <ImageView
- android:id="@+id/iv_find"
- android:layout_width="26dp"
- android:layout_height="34dp"
- android:src="@drawable/icon_find"
- android:layout_toRightOf="@+id/iv_show"
- android:layout_below="@+id/iv_show"
- android:layout_marginTop="4dp"/>
-
- <ImageView
- android:id="@+id/iv_home_menu"
- android:layout_width="26dp"
- android:layout_height="34dp"
- android:src="@drawable/icon_menu"
- android:layout_centerVertical="true"
- android:layout_marginRight="8dp"
- android:layout_alignParentRight="true"/>
-
- </RelativeLayout>
-
- </RelativeLayout>
结构就是使用相对布局,底层一个listview或者是viewpager等,然后在右下角再使用一个相对布局来实现菜单栏的布局就OK了。
三、动画的实现:
1、展开动画:
- public void openMenu() {
- reCircleMenu.animate().scaleX(1f).scaleY(1f).translationX(0).setDuration(300).start();
- mivShow.animate().alpha(1).scaleX(1f).scaleY(1f).translationX(0f).setDuration(300).start();
- mivHome.animate().alpha(1).scaleX(1f).scaleY(1f).translationX(0).translationY(0).setDuration(300).start();
- mivfind.animate().alpha(1).scaleX(1f).scaleY(1f).translationX(0).translationY(0).setDuration(300).start();
- mivMenu.animate().scaleX(1f).scaleY(1f).translationX(0).setDuration(300).start();
- }
主要就是几种动画(透明度、缩放、位移)的集合实现,展开后的效果就是刚开始初始化的效果,所以这里把透明度、位移、缩放还原就行了。
2、缩放动画:
- public void closeMenu() {
- reCircleMenu.animate().scaleX(0.3f).scaleY(0.3f).translationX(-dip2px(50)).setDuration(300).start();
- mivShow.animate().alpha(0).scaleX(10 / 3f).scaleY(10 / 3f).translationX(dip2px(60)).setDuration(300).start();
- mivHome.animate().alpha(0).scaleX(10 / 3f).scaleY(10 / 3f).translationX(dip2px(35)).translationY(dip2px(40)).setDuration(300)
- .start();
- mivfind.animate().alpha(0).scaleX(10 / 3f).scaleY(10 / 3f).translationX(dip2px(35)).translationY(-dip2px(40)).setDuration(300)
- .start();
- mivMenu.animate().scaleX(10 / 3f).scaleY(10 / 3f).translationX(-dip2px(60)).setDuration(300).start();
- }
这个就稍微复杂点,首先要同个多次测试找到合适的位移距离,其他的都不难。
四、滑动的监听:
- listView.setOnScrollListener(new OnScrollListener() {
-
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
- System.out.println("HOME PAGE SCROLL_STATE_TOUCH_SCROLL----");
-
- closeMenu();
- } else if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
- System.out.println("HOME PAGE SCROLL_STATE_FLING");
- } else if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
- System.out.println("HOME PAGE SCROLL_STATE_IDLE");
-
- openMenu();
- }
-
- }
-
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
-
-
- }
- });
在刚开始滑动时就关闭菜单,滑动停止时打开菜单即可,这个监听可以放到任何可以监听到滑动状态的事件中,不止是在listview中。
通过以上步骤就实现了如效果图的效果,哈哈 现在想想还是多么简单的。很多问题看似复杂,通过分解成小问题后,就不是什么大问题了,解决办法就很多了,然后大问题也就迎刃而解了! 实例源码下载