Android 一行代码实现炫酷Button
来源:互联网 发布:铁道工程就业 知乎 编辑:程序博客网 时间:2024/06/06 06:30
前言
以前有接触过这个,不过也只是看到github上面的,看起来很炫酷,最近有看动画这一方面,所以突然兴致大发, 简简单单实现一个自定义的View, 纯动画, 没有什么需要计算的地方.
效果图
使用方法
在app/build.gradle中添加下面一行代码:
dependencies { compile 'com.example.thatnight:animbutton:1.3'}
layout.xml中
<com.example.animbutton.AnimButton android:id="@+id/rl" android:layout_width="match_parent" android:layout_height="wrap_content" app:duration="300" app:start_text="login" app:end_text="error" ></com.example.animbutton.AnimButton>
需要修改属性的话, 可以按住ctrl+ 鼠标左键 点击fm_button_progress, 如下
<com.example.animbutton.AnimButton android:id="@+id/rl" android:layout_width="match_parent" android:layout_height="@dimen/button_height" anim:duration="300" //动画时长 anim:start_text="Login" //默认字符串 anim:end_text="Error" //错误字符串 />
- activity中
private AnimButton mButton;private ProgressBar mProgress;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = (AnimButton) findViewById(R.id.rl); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mButton.startAnimation(); } });}
就跟原先的Button一样的使用方法.很简单吧
主要代码
布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:anim="http://schemas.android.com/apk/res-auto" android:id="@+id/rl_button" android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="@dimen/button_height" android:layout_centerInParent="true" android:layout_margin="10dp" android:gravity="center" android:textColor="@color/white" android:textSize="18sp" /> </RelativeLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"> <ProgressBar android:id="@+id/pb_button" android:layout_width="wrap_content" android:layout_height="@dimen/button_height" android:layout_centerInParent="true" android:alpha="0" android:indeterminateDuration="300" /> </RelativeLayout></RelativeLayout>
很简单, 就一个button和一个progressbar, 这都是系统自带的应用, 我这里只不过是将它们组合在一起了而已
AnimButton
先来看看构造方法
public AnimButton(Context context) { this(context, null);}public AnimButton(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0);}public AnimButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AnimButton); mStartText = a.getString(R.styleable.AnimButton_start_text); mEndText = a.getString(R.styleable.AnimButton_end_text); mDuration = a.getInt(R.styleable.AnimButton_duration, 300); mNormalColor = a.getColor(R.styleable.AnimButton_color_normal, ContextCompat.getColor(context, R.color.colorPrimary)); mPressedColor = a.getColor(R.styleable.AnimButton_color_pressed, ContextCompat.getColor(context, R.color.colorPrimaryDark)); mProgressColor = a.getColor(R.styleable.AnimButton_color_progress, ContextCompat.getColor(context, R.color.colorAccent)); mTextColor = a.getColor(R.styleable.AnimButton_color_text, ContextCompat.getColor(context, R.color.colorAccent)); mRadius = a.getFloat(R.styleable.AnimButton_button_radius, 0); a.recycle(); //inflate layout LayoutInflater.from(context).inflate(R.layout.fm_button_progress, this, true); mProgress = (ProgressBar) findViewById(R.id.pb_button); setProgressDrawable(context); mTarget = (Button) findViewById(R.id.button); setWrapper(mTarget); buildDrawableState(); if (mStartText != null && mStartText.length() > 0) { mTarget.setText(mStartText); }}
这里三个构造方法其实只有一个会运行, 就是第三个, 其他两个修改了==this(…)==, 这里是个坑
这里先是获取自定义的属性, 然后是很普通的绑定控, setWrapper后面会讲
接下里看看buildDrawableState(), 也就是创建button和ProgressBar的样式
/** * change the button drawable */private void buildDrawableState() { float radius[] = new float[]{mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius}; StateListDrawable drawable = new StateListDrawable(); RoundRectShape rectShape = new RoundRectShape(radius, null, null); ShapeDrawable pressedDrawable = new ShapeDrawable(rectShape); pressedDrawable.getPaint().setColor(mPressedColor); drawable.addState(mPressedState, pressedDrawable); ShapeDrawable normalDrawable = new ShapeDrawable(rectShape); normalDrawable.getPaint().setColor(mNormalColor); drawable.addState(mNormalState, normalDrawable); mTarget.setBackground(drawable); mTarget.setTextColor(mTextColor);}/** * change the progressbar drawable * Build.VERSION >= 21(5.0) * @param context */private void setProgressDrawable(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { RotateDrawable rotateDrawable = (RotateDrawable) ContextCompat.getDrawable(context, R.drawable.bg_progress); GradientDrawable gradientDrawable = (GradientDrawable) rotateDrawable.getDrawable(); if (gradientDrawable != null) { gradientDrawable.setColors(new int[]{mProgressColor, Color.WHITE}); rotateDrawable.setDrawable(gradientDrawable); mProgress.setIndeterminateDrawable(rotateDrawable); } }}
我们看看主要的动画代码
开始动画
public void startAnimation() {if (mStartSet == null) { initStartAnim(); initErrorAnim();}mStartSet.start();}
再看看初始化动画这里, 使用的是ObjectAnimator对象动画,我觉得实现起来很简单.
if (mProgress == null || mTarget == null) { try { throw new Exception("No binding a progress or target"); } catch (Exception e) { e.printStackTrace(); }}mStartSet = new AnimatorSet();ObjectAnimator progressAnim = ObjectAnimator.ofFloat(mProgress, "alpha", 1);progressAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); } @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); mTarget.setText(""); mTarget.setClickable(false); }});ObjectAnimator startAnim = ObjectAnimator.ofInt(mViewWrapper, "width", mWidth, mHeight);startAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); }});mStartSet.setDuration(mDuration);mStartSet.playTogether(progressAnim, startAnim);
其实效果就是改变button的宽度, 主要是使用了viewwrapper来修改button的宽度
什么是ViewWrapper, 就是用来实现button的width,get和set方法, 虽然本来button就有这两个方法,但是是写死的了.
private static class ViewWrapper {private View mTarget;public ViewWrapper(View target) { mTarget = target;}public int getWidth() { return mTarget.getLayoutParams().width;}public void setWidth(int width) { mTarget.getLayoutParams().width = width; mTarget.requestLayout();}}
复原动画这里就不贴代码了,同样的道理. 那么动画就这么完成了, 不对, 我还没讲button的宽度和高度怎么获取的呢 .
之前也遇到很多的问题, 所以我今天要讲.
@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (mWidth == 0 && mHeight == 0) { mWidth = mTarget.getMeasuredWidth(); mHeight = mTarget.getMeasuredHeight(); mLeft = mTarget.getLeft(); }}
哇, 这么点代码的吗?是的,之前没弄明白的时候, 就一直碰壁, 到处百度google,不得不说, 还是要好好掌握这个基础啊.
GitHub
我做了个这样子的项目, 我觉的我可以让别人很方便的使用, 于是乎, 又有了另外一篇博客, 如何将项目上传到jcenter, 让别人使用gradle一行代码就能是实现,.
https://github.com/thatnight/AnimButton
- Android 一行代码实现炫酷Button
- android button点击事件(第一行代码android学习笔记)
- Xcode中不用一行代码实现button圆角
- Android代码实现自定义Button
- 一行代码实现android文件下载
- 一行代码实现Android文件下载
- Android 实现沉浸式只需一行代码
- 一行代码实现strlen
- 一行代码实现阶乘
- Android第一行代码
- button代码实现点击
- android Titlebar一行代码实现沉浸式效果
- android:一行代码实现沉浸式布局效果
- Android自定义控件-一行代码实现加载对话框
- 一行代码实现Android软键盘与EditText的交互
- 一行代码完美实现Android沉浸式效果
- android:一行代码实现沉浸式布局效果
- android一行代码实现沉浸式布局效果
- 排序相关总结(复杂度、稳定性、比较)
- JAVA高并发多线程必须懂的50个问题
- 无序数组中找到中位数
- Spring容器中的Bean
- Keepalived安装与配置
- Android 一行代码实现炫酷Button
- poj 2524 Ubiquitous Religions(并查集)
- IntelliJ Idea各种技巧设置笔记和错误解决
- 第3周项目1 顺序表的基本运算
- python检测文件的MD5值
- 异地恋的我们
- 前端性能优化----yahoo前端性能团队总结的35条黄金定律
- Redis源码阅读笔记--六大数据结构和五大对象
- Mysql查询结果顺序按 in() 中ID 的顺序排列