首页 > 代码库 > 抛弃Residemenu来实现QQ5.0UI

抛弃Residemenu来实现QQ5.0UI

        转载清注明:http://blog.csdn.net/eclipsexys

        自从QQ 5.0发布,新的QQ UI就成了大家模仿的众矢之地,不过大家模仿的时候,一般都会使用到一个开源控件,Residemenu,相信大家对这个开源框架还是很熟悉的,刚出来的时候,确实很惊艳,但是,对于初学者或者只是想实现一个很简单的效果的朋友来说,用这个框架就有点大材小用了,其实,利用Android原生的控件,我们也能实现这样一个酷眩的效果,今天的主角是SlidingPaneLayout,这个组件是在support v4里面新增的控件,不熟悉的朋友可以看看support v4里面的sample,非常简单。

国际惯例,先上图:


大家可以看见,跟Residemenu实现的效果基本一致。


结构非常简单,一个容器,2个fragment,就完成了。

让我们现来看看布局:

容器类:

<android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:id="@+id/main"
    android:background="@drawable/main_bg"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/main_menu"
        android:layout_width="200dp"
        android:layout_height="match_parent" >
    </FrameLayout>

    <FrameLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </FrameLayout>

</android.support.v4.widget.SlidingPaneLayout>

就是SlidingPaneLayout里面放了2个fragment,第一个默认是左边的,也就是初始隐藏的,第2个就是右边滑动的

让我们再来看看2个fragment:

Menu fragment:

package com.xys.fastword.fragment;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.xys.fastword.R;

public class MenuFragment extends Fragment {
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		return inflater.inflate(R.layout.menu_frg, container, false);
	}
}


布局:

<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"
    android:background="@null" >

    <LinearLayout
        android:id="@+id/ll"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="30dp"
        android:gravity="center_vertical" >

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:src=http://www.mamicode.com/"@drawable/ic_launcher" />>


Container Fragment:

package com.xys.fastword.fragment;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.BounceInterpolator;
import android.widget.ImageView;
import android.widget.TextView;

import com.xys.fastword.R;

public class ContainerFragment extends Fragment implements OnClickListener {

	private ImageView ivRecite;
	private View view;
	private TextView tvTitle;
	private ImageView btnLeft;
	private ImageView btnRight;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		view = inflater.inflate(R.layout.container_frg, container, false);
		ivRecite = (ImageView) view.findViewById(R.id.iv_recite);
		ivRecite.setOnClickListener(this);
		return view;
	}

	@Override
	public void onClick(View v) {
		final View view = v;
		PropertyValuesHolder pvX = PropertyValuesHolder.ofFloat("scaleX", 1F,
				0.8F, 1F);
		PropertyValuesHolder pvY = PropertyValuesHolder.ofFloat("scaleY", 1F,
				0.8F, 1F);
		ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(v, pvX,
				pvY);
		animator.setInterpolator(new BounceInterpolator());
		animator.start();
		animator.addListener(new AnimatorListenerAdapter() {

			@Override
			public void onAnimationEnd(Animator animation) {
				super.onAnimationEnd(animation);
				switch (view.getId()) {
				case R.id.iv_recite:
					break;

				default:
					break;
				}
			}
		});

	}
}


布局:

<LinearLayout 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"
    android:background="@android:color/holo_blue_bright"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <ImageView
            android:id="@+id/iv_recite"
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:layout_marginLeft="30dp"
            android:layout_marginTop="30dp"
            android:background="#777777" />

        <ImageView
            android:id="@+id/imageView2"
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:layout_below="@id/iv_recite"
            android:layout_marginLeft="30dp"
            android:layout_marginTop="20dp"
            android:background="#777777"
            android:src=http://www.mamicode.com/"@drawable/ic_launcher" />>


为了娱乐,我给布局的一个imageview加了个点击动画,不需要的可以无视。


最后,在容器中就可以来控制了:

package com.xys.fastword.activity;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.widget.SlidingPaneLayout;
import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
import android.view.View;
import android.widget.FrameLayout;

import com.xys.fastword.R;
import com.xys.fastword.fragment.ContainerFragment;
import com.xys.fastword.fragment.MenuFragment;

public class MainActivity extends Activity {

	private SlidingPaneLayout mSPLMain;
	private FrameLayout mFLMenu;
	private FrameLayout mFLContainer;

	private FragmentManager mFrgManager;
	private FragmentTransaction mFrgTransaction;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.fw_main);
		mFrgManager = getFragmentManager();
		initViews();

		bindEvents();
	}

	private void bindEvents() {
		mSPLMain.setPanelSlideListener(new PanelSlideListener() {

			@Override
			public void onPanelSlide(View arg0, float v) {
				mFLMenu.setScaleY(v / 2 + 0.5F);
				mFLMenu.setScaleX(v / 2 + 0.5F);
				mFLMenu.setAlpha(v);
				mFLContainer.setScaleY(1 - v / 5);
			}

			@Override
			public void onPanelOpened(View arg0) {
			}

			@Override
			public void onPanelClosed(View arg0) {
			}
		});
	}

	private void initViews() {
		mSPLMain = (SlidingPaneLayout) findViewById(R.id.main);
		mFLMenu = (FrameLayout) findViewById(R.id.main_menu);
		mFLContainer = (FrameLayout) findViewById(R.id.main_container);

		mFrgTransaction = mFrgManager.beginTransaction();
		mFrgTransaction.add(R.id.main_menu, new MenuFragment(), "mMenuFrg");
		mFrgTransaction.add(R.id.main_container, new ContainerFragment(),
				"mContainerFrg");
		mFrgTransaction.commit();
	}

}

实现效果的关键就在于setPanelSlideListener中的onPanelSlide(View arg0, float v)的参数v:

参数v就是滑动时的距离参数,0-1的变化,那么,我们就可以根据这个值来通过各种函数的变化,来获取我们所需要的值,这样就实现了一个插值器了,实现动画也就so easy了。



抛弃Residemenu来实现QQ5.0UI