1. 程式人生 > >Android懸浮縮放選單的實現

Android懸浮縮放選單的實現

先看效果圖:(文章結尾有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----");
					// isScrool = true;
					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");
					// isScrool = false;
					openMenu();
				}

			}

			@Override
			public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
				// TODO Auto-generated method stub

			}
		});
在剛開始滑動時就關閉選單,滑動停止時開啟選單即可,這個監聽可以放到任何可以監聽到滑動狀態的事件中,不止是在listview中。

通過以上步驟就實現瞭如效果圖的效果,哈哈 現在想想還是多麼簡單的。很多問題看似複雜,通過分解成小問題後,就不是什麼大問題了,解決辦法就很多了,然後大問題也就迎刃而解了! 例項原始碼下載