Android自定义View--使用ViewAnimator实现一个提交按钮
来源:互联网 发布:java maven log4j2 编辑:程序博客网 时间:2024/05/22 07:45
效果图
准备知识
merge
标签的使用,可以参考Android 布局优化之include与merge- ViewAnimator
Android
自定义组件
SendCommentButton
新建SendCommentButton
继承自ViewAnimator
,而ViewAnimator
是继承自FrameLayout
的。
public class SendCommentButton extends ViewAnimator{ //通过代码new执行该方法 public SendCommentButton(Context context) { super(context); init(); } //通过xml引入会执行该方法 public SendCommentButton(Context context, AttributeSet attrs) { super(context, attrs); init(); }}
init()
方法
private void init() { LayoutInflater.from(getContext()).inflate(R.layout.view_send_comment_button, this, true); }
把布局依附到该控件上 R.layout.view_send_comment_button
布局
<?xml version="1.0" encoding="utf-8"?><merge xmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:id="@+id/tvSend" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="SEND" android:textColor="#ffffff" android:textSize="12sp" /> <TextView android:id="@+id/tvDone" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="✓" android:textColor="#ffffff" android:textSize="12sp" /></merge>
执行init()
方法之后会回调ViewAnimator
的addView
方法,我们来看看ViewAnimator
是怎么处理的
...... @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { super.addView(child, index, params); if (getChildCount() == 1) { child.setVisibility(View.VISIBLE); } else { child.setVisibility(View.GONE); } if (index >= 0 && mWhichChild >= index) { // Added item above current one, increment the index of the displayed child setDisplayedChild(mWhichChild + 1); } } ......
从上面可以看到把第一个子View
设置为可见,其他设置GONE
,也就是说merge
的✓
设置为GONE
了。
接下来我们补充SendCommentButton
其他逻辑代码
public class SendCommentButton extends ViewAnimator implements View.OnClickListener { public static final int STATE_SEND = 0; public static final int STATE_DONE = 1; private static final long RESET_STATE_DELAY_MILLIS = 2000; private int currentState; private OnSendClickListener onSendClickListener; //通过代码new执行该方法 public SendCommentButton(Context context) { super(context); init(); } //通过xml引入会执行该方法 public SendCommentButton(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { LayoutInflater.from(getContext()).inflate(R.layout.view_send_comment_button, this, true); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); currentState = STATE_SEND; setOnClickListener(this); } @Override public void onClick(View view) { if (onSendClickListener != null) { onSendClickListener.onSendClickListener(this); } } @Override protected void onDetachedFromWindow() { removeCallbacks(revertStateRunnable); super.onDetachedFromWindow(); } public void setCurrentState(int state) { if (state == currentState) { return; } currentState = state; if (state == STATE_DONE) { setEnabled(false); postDelayed(revertStateRunnable, RESET_STATE_DELAY_MILLIS); setInAnimation(getContext(), R.anim.slide_in_done); setOutAnimation(getContext(), R.anim.slide_out_send); } else if (state == STATE_SEND) { setEnabled(true); setInAnimation(getContext(), R.anim.slide_in_send); setOutAnimation(getContext(), R.anim.slide_out_done); } showNext(); } private Runnable revertStateRunnable = new Runnable() { @Override public void run() { setCurrentState(STATE_SEND); } }; public interface OnSendClickListener { void onSendClickListener(View v); } public void setOnSendClickListener(OnSendClickListener onSendClickListener) { this.onSendClickListener = onSendClickListener; }}
上面定义了两种状态,暴露了一个接口和设置了进入和进出动画。这里解析一下ViewAnimator
的showNext()
方法,在ViewAnimator
的源码中
...... public void showNext() { setDisplayedChild(mWhichChild + 1); } ......
showNext
会调用setDisplayedChild
方法
/** * Sets which child view will be displayed. *设置哪个子View将被显示 * @param whichChild the index of the child view to display 要显示子view的下标 */ public void setDisplayedChild(int whichChild) { mWhichChild = whichChild; if (whichChild >= getChildCount()) { mWhichChild = 0; } else if (whichChild < 0) { mWhichChild = getChildCount() - 1; } boolean hasFocus = getFocusedChild() != null; // This will clear old focus if we had it showOnly(mWhichChild); if (hasFocus) { // Try to retake focus if we had it requestFocus(FOCUS_FORWARD); } }
setDisplayedChild
中的主要展示逻辑交给了showOnly
方法
/** * Shows only the specified child. The other displays Views exit the screen, * optionally with the with the {@link #getOutAnimation() out animation} and * the specified child enters the screen, optionally with the * {@link #getInAnimation() in animation}. * * @param childIndex The index of the child to be shown. * @param animate Whether or not to use the in and out animations, defaults * to true. */ void showOnly(int childIndex, boolean animate) { final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (i == childIndex) { if (animate && mInAnimation != null) { child.startAnimation(mInAnimation); } child.setVisibility(View.VISIBLE); mFirstTime = false; } else { if (animate && mOutAnimation != null && child.getVisibility() == View.VISIBLE) { child.startAnimation(mOutAnimation); } else if (child.getAnimation() == mInAnimation) child.clearAnimation(); child.setVisibility(View.GONE); } } } /** * Shows only the specified child. The other displays Views exit the screen * with the {@link #getOutAnimation() out animation} and the specified child * enters the screen with the {@link #getInAnimation() in animation}. *正在展示的view退出屏幕,展示指定的view,指定的view以getInAnimation的动画进入,退出的view以getOutAnimation的动画退出 * @param childIndex The index of the child to be shown. */ void showOnly(int childIndex) { final boolean animate = (!mFirstTime || mAnimateFirstTime); showOnly(childIndex, animate); }
重点看下这段代码
for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (i == childIndex) { if (animate && mInAnimation != null) { child.startAnimation(mInAnimation); } child.setVisibility(View.VISIBLE); mFirstTime = false; } else { if (animate && mOutAnimation != null && child.getVisibility() == View.VISIBLE) { child.startAnimation(mOutAnimation); } else if (child.getAnimation() == mInAnimation) child.clearAnimation(); child.setVisibility(View.GONE); } }
从上面可以看到ViewAnimator
把我们之前设置的setInAnimation(getContext(), R.anim.slide_in_done);
应用到进入和退出
setOutAnimation(getContext(), R.anim.slide_out_send);View
上。
下载地址
参考
阅读全文
0 0
- Android自定义View--使用ViewAnimator实现一个提交按钮
- ViewAnimator实现按钮切换动画
- Android自定义View实现开关按钮
- 自定义View实战--实现一个清新美观的加载按钮
- Android 实现一个简单的自定义View
- android自定义view实现一个钟表
- 自定义View:自定义属性(自定义按钮实现)
- Android 自定义View实现动态炫酷按钮
- Android 自定义view的实现 滑动按钮案列
- 【Android自定义View】随机数按钮
- Android自定义View之自定义开关按钮
- Android自定义View--使用NestScrolling机制实现一个上下滑动退出Layout
- [Android开发] 自定义View之重写View非常简单实现开关按钮SwitchView
- Android自定义View实现
- Android 实现自定义View
- Android实现自定义View
- Android实现自定义View
- android实现自定义view
- 【Java】spring 模版 jdbcTemplate
- HookProc 和 CallNextHookEx
- js学习1
- layer关闭刷新父界面
- Resource Manager关闭引起的自动JOB无法调用
- Android自定义View--使用ViewAnimator实现一个提交按钮
- MongoDB 3.4安装及注册windows服务
- oracle的序列号(sequence)
- LeetCode 1. Two Sum
- 评价一个事物的好坏方法学
- HBase(一)概述
- 图像处理学习1
- 南阳理工 题目63 小猴子下落
- selinux-ls