100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Android自定义弹出菜单+动画实现

Android自定义弹出菜单+动画实现

时间:2023-01-19 22:17:15

相关推荐

Android自定义弹出菜单+动画实现

看到网上一个Demo里面弹出菜单的动画效果很好看,自己就利用工作空余时间也写了一下。具体实现如下:

1 自定义一个显示Icon的ImageView,主要用来判断该ImageView是否需要放在父布局底部水平中心位置

import android.content.Context;

import android.content.res.TypedArray;

import android.util.AttributeSet;

import android.widget.ImageView;

/**

* Created by crab on 14-9-26.

*/

public class BottomCenterImageView extends ImageView {

private boolean mLayoutParentBottomCenter=false;

public BottomCenterImageView(Context context) {

super(context);

}

public BottomCenterImageView(Context context, AttributeSet attrs) {

super(context, attrs);

TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.HoriAnimationLayout,0, 0);

mLayoutParentBottomCenter=a.getBoolean(R.styleable.HoriAnimationLayout_bottomCenter,false);

a.recycle();

}

public BottomCenterImageView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.HoriAnimationLayout,defStyle,0);

mLayoutParentBottomCenter=a.getBoolean(R.styleable.HoriAnimationLayout_bottomCenter,false);

a.recycle();

}

public boolean isLayoutParentBottomCenter(){

return mLayoutParentBottomCenter;

}

}

2 建立一个容纳要显示ImageView的容器类

import android.content.Context;

import android.util.AttributeSet;

import android.view.View;

import android.view.animation.Animation;

import android.view.animation.RotateAnimation;

import android.view.animation.TranslateAnimation;

import android.widget.LinearLayout;

/**

* Created by crab on 14-9-26.

*/

public class HoriAnimationLayout extends LinearLayout{

private int mTwoLineHeight=0;

private int mOnewLineHeight=0;

//是否有一个view放在该布局的底部水平中间位置

private boolean mHasChildLayoutBottom=false;

public static final int STATE_OPEN=0;

public static final int STATE_CLOSE=1;

private static final long ANIMATION_DURATION=500L;

private int mState=STATE_CLOSE;

public HoriAnimationLayout(Context context) {

super(context);

init(context);

}

@Override

protected void onFinishInflate() {

super.onFinishInflate();

BottomCenterImageView child=null;

int count=getChildCount();

for(int i=0;i<count;i++){

child= (BottomCenterImageView) getChildAt(i);

if(!child.isLayoutParentBottomCenter()){

child.setVisibility(View.INVISIBLE);

}else{

child.setOnClickListener(new OnClickListener(){

@Override

public void onClick(View v) {

if(mState==STATE_CLOSE){

open();

}else{

close();

}

}

});

}

}

}

public HoriAnimationLayout(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public HoriAnimationLayout(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init(context);

}

private void init(Context context){

mOnewLineHeight=(int) getResources().getDimension(R.dimen.circle_icon_size);

mTwoLineHeight=(int) getResources().getDimension(R.dimen.circle_anim_parent_height);

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

int childCount=getChildCount();

if(childCount==0){

throw new RuntimeException("请添加一个或者更多CircleAnimationImageView");

}

int gapCount=childCount-1;

int gap=0;

int leftOffset=0;

BottomCenterImageView child=null;

if(mHasChildLayoutBottom){

gapCount=gapCount-1;

}

if(gapCount<=0){

if(gapCount==-1){

//只有一个并且需要直接布局到底部

child= (BottomCenterImageView) getChildAt(0);

child.layout((r-l)/2-child.getMeasuredWidth()/2,getMeasuredHeight()-child.getMeasuredHeight(),(r-l)/2+child.getMeasuredWidth()/2,getMeasuredHeight());

return;

}else if(gapCount==0){

gap=(r-l)/2-mOnewLineHeight/2;

}

}else{

gap=(r-l-(gapCount+1)*mOnewLineHeight)/gapCount;

}

for(int i=0;i<childCount;i++){

child= (BottomCenterImageView) getChildAt(i);

boolean isLayoutBottomCenter=child.isLayoutParentBottomCenter();

if(isLayoutBottomCenter){

child.layout((r-l)/2-child.getMeasuredWidth()/2,getMeasuredHeight()-child.getMeasuredHeight(),(r-l)/2+child.getMeasuredWidth()/2,getMeasuredHeight());

}else{

child.layout(leftOffset,0,leftOffset+child.getMeasuredWidth(),child.getMeasuredHeight());

leftOffset=leftOffset+child.getMeasuredWidth()+gap;

}

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int width=MeasureSpec.getSize(widthMeasureSpec);

int childCount=getChildCount();

for(int i=0;i<childCount;i++){

BottomCenterImageView child= (BottomCenterImageView) getChildAt(i);

if(child.isLayoutParentBottomCenter()){

mHasChildLayoutBottom=true;

}

int childMeasureSize=MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY,mOnewLineHeight);

child.measure(childMeasureSize,childMeasureSize);

}

int height=0;

if(mHasChildLayoutBottom){

height=mTwoLineHeight;

}else{

height=mOnewLineHeight;

}

setMeasuredDimension(width, height);

}

private void open(){

if(mState==STATE_OPEN){

return;

}

mState=STATE_OPEN;

float dstX=getMeasuredWidth()/2-mOnewLineHeight/2;

float dstY=getMeasuredHeight()-mOnewLineHeight;

int childCount=getChildCount();

Animation[] animations=new Animation[childCount];

for(int i=0;i<childCount;i++) {

final BottomCenterImageView child = (BottomCenterImageView) getChildAt(i);

if(!child.isLayoutParentBottomCenter()) {

float fromX = dstX - child.getLeft();

float fromY = dstY - child.getTop();

float toX = 0;

float toY = 0;

TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, fromX, Animation.ABSOLUTE, toX,

Animation.ABSOLUTE, fromY, Animation.ABSOLUTE, toY);

translateAnimation.setDuration(ANIMATION_DURATION);

translateAnimation.setAnimationListener(new VisbleStateAniamtionListener(child, true));

animations[i] = translateAnimation;

}else{

RotateAnimation rotateAnimation=new RotateAnimation(180,360,child.getWidth()/2,child.getHeight()/2);

rotateAnimation.setDuration(ANIMATION_DURATION);

rotateAnimation.setFillAfter(true);

animations[i]=rotateAnimation;

}

}

for(int i=0;i<childCount;i++){

final BottomCenterImageView child = (BottomCenterImageView) getChildAt(i);

child.startAnimation(animations[i]);

}

}

private void close(){

if(mState==STATE_CLOSE){

return;

}

mState=STATE_CLOSE;

float dstX=getMeasuredWidth()/2-mOnewLineHeight/2;

float dstY=getMeasuredHeight()-mOnewLineHeight;

int childCount=getChildCount();

Animation[] animations=new Animation[childCount];

for(int i=0;i<childCount;i++) {

final BottomCenterImageView child = (BottomCenterImageView) getChildAt(i);

if(!child.isLayoutParentBottomCenter()) {

float fromX = 0;

float fromY = 0;

float toX = dstX - child.getLeft();

float toY = dstY - child.getTop();

TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, fromX, Animation.ABSOLUTE, toX,

Animation.ABSOLUTE, fromY, Animation.ABSOLUTE, toY);

translateAnimation.setDuration(ANIMATION_DURATION);

translateAnimation.setAnimationListener(new VisbleStateAniamtionListener(child, false));

animations[i] = translateAnimation;

}else{

RotateAnimation rotateAnimation=new RotateAnimation(0,180,child.getWidth()/2,child.getHeight()/2);

rotateAnimation.setDuration(ANIMATION_DURATION);

rotateAnimation.setFillAfter(true);

animations[i]=rotateAnimation;

}

}

for(int i=0;i<childCount;i++){

final BottomCenterImageView child = (BottomCenterImageView) getChildAt(i);

child.startAnimation(animations[i]);

}

}

private class VisbleStateAniamtionListener implements Animation.AnimationListener{

private View mView;

private boolean mVisible;

public VisbleStateAniamtionListener(View view,boolean visible){

mView=view;

mVisible=visible;

}

@Override

public void onAnimationStart(Animation animation) {

if(mView.getVisibility()!=View.VISIBLE){

mView.setVisibility(View.VISIBLE);

}

}

@Override

public void onAnimationEnd(Animation animation) {

if(mVisible){

mView.setVisibility(View.VISIBLE);

}else{

mView.setVisibility(View.INVISIBLE);

}

}

@Override

public void onAnimationRepeat(Animation animation) {

}

}

}

3定义布局文件,用到的图片资源可以自己去网上下载,最好用园行图片

<RelativeLayout

xmlns:android="/apk/res/android"

xmlns:customApp="/apk/res-auto"

android:layout_width="match_parent"

android:background="#FFCCCCCC"

android:layout_height="match_parent">

<com.example.crab.mycameratest.HoriAnimationLayout

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:orientation="horizontal"

android:layout_marginLeft="20dp"

android:layout_marginRight="20dp"

>

<com.example.crab.mycameratest.BottomCenterImageView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/pg_thrid_facebook_click"

/>

<com.example.crab.mycameratest.BottomCenterImageView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/pg_thrid_kupan_click"

/>

<com.example.crab.mycameratest.BottomCenterImageView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/pg_thrid_sina_click"

/>

<com.example.crab.mycameratest.BottomCenterImageView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/pg_thrid_twitter_click"

/>

<com.example.crab.mycameratest.BottomCenterImageView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/pg_thrid_qq_click"

/>

<com.example.crab.mycameratest.BottomCenterImageView

android:id="@+id/animationTrigger"

customApp:bottomCenter="true"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/pg_thrid_qq_click"

/>

</com.example.crab.mycameratest.HoriAnimationLayout>

</RelativeLayout>

4定义自己需要用到的一些自定义资源与样式

dimens.xml

<resources>

<dimen name="circle_icon_size">40dp</dimen>

<dimen name="circle_anim_parent_height">128dp</dimen>

</resources>

attrs.xml

<declare-styleable name="HoriAnimationLayout">

<attr name="bottomCenter" format="boolean"/>

</declare-styleable>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。