自定义按钮实现水波点击效果
2017-09-29 22:16
405 查看
1运行效果
2自定义布局
public class RevealLayout extends LinearLayout implements Runnable { private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private int[] mLocationInScreen = new int[2]; private float mCenterX; private float mCenterY; private int mTargetWidth; private int mTargetHeight; private int mMaxBetweenWidthAndHeight; private int mMinBetweenWidthAndHeight; private int mMaxRevealRadius; private int mRevealRadiusGap; private int mRevealRadius = 0; private boolean mShouldDoAnimation = false; private boolean mIsPressed = false; private View mTouchTarget; private int INVALIDATE_DURATION = 40; private DispatchUpTouchEventRunnable mDispatchUpTouchEventRunnable = new DispatchUpTouchEventRunnable(); public RevealLayout(Context context) { super(context); init(); } public RevealLayout(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RevealLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ setWillNotDraw(false); mPaint.setColor(getResources().getColor(#1b000000)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); this.getLocationOnScreen(mLocationInScreen); } private void initParametersForChild(MotionEvent event, View view){ mCenterX = event.getX(); mCenterY = event.getY(); mTargetWidth = view.getMeasuredWidth(); mTargetHeight = view.getMeasuredHeight(); mMinBetweenWidthAndHeight = Math.min(mTargetWidth,mTargetHeight); mMaxBetweenWidthAndHeight = Math.max(mTargetWidth,mTargetHeight); mRevealRadius = 0; mShouldDoAnimation = true; mIsPressed = true; mRevealRadiusGap = mMinBetweenWidthAndHeight / 8; int[] location = new int[2]; view.getLocationOnScreen(location); int left = location[0] - mLocationInScreen[0]; int transformedCenterX = (int)mCenterY - left; mMaxRevealRadius = Math.max(transformedCenterX,mTargetWidth - transformedCenterX); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if(!mShouldDoAnimation || mTargetWidth <= 0 || mTouchTarget == null){ return; } if(mRevealRadius > mMinBetweenWidthAndHeight / 2){ mRevealRadius += mRevealRadiusGap * 4; }else { mRevealRadius += mRevealRadiusGap; } this.getLocationOnScreen(mLocationInScreen); int[] location = new int[2]; mTouchTarget.getLocationOnScreen(location); int left = location[0] - mLocationInScreen[0]; int top = location[1] - mLocationInScreen[1]; int right = left + mTouchTarget.getMeasuredWidth(); int bottom = top + mTouchTarget.getMeasuredHeight(); canvas.save(); canvas.clipRect(left,top,right,bottom); canvas.drawCircle(mCenterX,mCenterY,mRevealRadius,mPaint); canvas.restore(); if(mRevealRadius <= mMaxRevealRadius){ postInvalidateDelayed(INVALIDATE_DURATION,left,top,right,bottom); }else if(!mIsPressed){ mShouldDoAnimation = false; postInvalidateDelayed(INVALIDATE_DURATION,left,top,right,bottom); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { int x = (int) ev.getRawX(); int y = (int) ev.getRawY(); int action = ev.getAction(); if(action == MotionEvent.ACTION_DOWN){ View touchTarget = getTouchTarget(this,x,y); if(touchTarget != null && touchTarget.isClickable() && touchTarget.isEnabled()){ mTouchTarget = touchTarget; initParametersForChild(ev,touchTarget); postInvalidateDelayed(INVALIDATE_DURATION); } }else if (action == MotionEvent.ACTION_UP){ mIsPressed = false; postInvalidateDelayed(INVALIDATE_DURATION); mDispatchUpTouchEventRunnable.event = ev; postDelayed(mDispatchUpTouchEventRunnable,40); return true; }else if (action == MotionEvent.ACTION_CANCEL){ mIsPressed = false; postInvalidateDelayed(INVALIDATE_DURATION); } return super.dispatchTouchEvent(ev); } private View getTouchTarget(View view,int x, int y){ View target = null; ArrayList<View> TouchableView = view.getTouchables(); for (View child : TouchableView){ if(isTouchPointInView(child,x,y)){ target = child; break; } } return target; } private boolean isTouchPointInView(View view, int x, int y){ int[] location = new int[2]; view.getLocationOnScreen(location); int left = location[0]; int top = location[1]; int right = left + view.getMeasuredWidth(); int bottom = top + view.getMeasuredHeight(); if(view.isClickable() && y >= top && y <= bottom && x >= left && x <= right){ return true; } return false; } @Override public boolean performClick() { postDelayed(this,400); return true; } @Override public void run() { super.performClick(); } private class DispatchUpTouchEventRunnable implements Runnable{ public MotionEvent event; @Override public void run() { if(mTouchTarget == null || !mTouchTarget.isEnabled()){ return; } if (isTouchPointInView(mTouchTarget,(int)event.getRawX(),(int)event.getRawY())){ mTouchTarget.performClick(); } } } }
3布局activity_main
?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:background="#ffffff" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.my.waterbatton.ui.RevealLayout android:id="@+id/layout1" android:gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/btn1" style="@style/AppTheme.Button.Green" android:enabled="true" android:text="Button" android:layout_width="match_parent" /> </com.my.waterbatton.ui.RevealLayout> <com.my.waterbatton.ui.RevealLayout android:id="@+id/layout2" android:layout_width="match_parent" android:layout_marginTop="20dp" android:orientation="vertical" android:layout_height="wrap_content"> <Button android:id="@+id/button1" style="@style/AppTheme.Button.Green" android:layout_width="200dp" android:enabled="true" android:text="Button" /> <Button android:id="@+id/button2" style="@style/AppTheme.Button.Green" b491 android:layout_margin="10dp" android:enabled="true" android:text="Button" /> <Button android:id="@+id/button3" style="@style/AppTheme.Button.Highlight" android:layout_margin="10dp" android:enabled="true" android:text="Button" /> <Button android:id="@+id/button4" style="@style/AppTheme.Button.Highlight" android:layout_height="100dp" android:layout_margin="10dp" android:enabled="true" android:text="Button" /> </com.my.waterbatton.ui.RevealLayout> </LinearLayout>
4 styles定义重复代码
<style name="AppTheme.Button"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">44dp</item> <item name="android:textSize">18dp</item> </style> <style name="AppTheme.Button.Green"> <item name="android:background">#0ac39e</item> <item name="android:textColor">#ffffff</item> </style> <style name="AppTheme.Button.Highlight"> <item name="android:background">#4185f2</item> <item name="android:textColor">#ffffff</item> </style>
源码下载
相关文章推荐
- 自定义Layout实现Android 5.0 Material Design的点击任意View的水波效果
- css美化number类型输入框美化实现自定义+、-号点击按钮增减效果
- Android 自定义View--实现带有按钮点击效果的自动补全输入框(搜索框)
- TextView实现超链接并自定义点击效果
- css实现按钮点击效果(超简单)
- Unity 实现按钮点击 某物体缓慢放大效果 比如打开商店
- android Ripple effect 点击 水波效果 自定义背景颜色
- iOS UIPanGestureRecognizer(拖动手势) 和 点击按钮 实现类似左抽屉的效果
- Android中动画实现单击按钮控制开屏关屏效果(系统animation实现、scrollTo实现、自定义scrollTo实现)
- ImageButton自定义按钮的按下效果的高效实现方法(非一般)
- jquery 实现 点击按钮后倒计时效果,多用于实现发送手机验证码、邮箱验证码
- 自定义Notification实现按钮点击事件
- 点击按钮,实现60秒倒计时效果(发送手机验证码)
- HtmlUnit实现模拟浏览器点击按钮的效果
- IOS之UI--自定义按钮实现代理监听点击事件
- jquery 实现 点击按钮后倒计时效果,多用于实现发送手机验证码、邮箱验证码
- css3 实现按钮点击动画效果(加工)
- 关于在自定义View中添加Button按钮以及实现点击事件
- CSS3点击按钮实现背景渐变动画效果
- jquery 实现 点击按钮后倒计时效果,多用于实现发送手机验证码、邮箱验证码