一个可以在界面顶部展现的自定义 View
来源:互联网 发布:java的swing界面设计 编辑:程序博客网 时间:2024/04/30 03:17
这个源码十分简单,没啥可说的.只有一点提一下,看到有些控件达到背景色的效果,是动态填加一个带背景色父布局实现的.
我这里是在画布上动态绘制的.
GitHub 地址: TranslationView
源码如下:
public class TranslationView extends FrameLayout { private static final String TAG = "TranslationView"; private static final int DEFAULT_COLOR = 0x50000000; private int mShadowColor = DEFAULT_COLOR; private boolean mIsShow = false; private View mTranslationView; private ObjectAnimator mShowAni; private ObjectAnimator mHideAni; public TranslationView(Context context) { super(context, null); } public TranslationView(Context context, AttributeSet attrs) { super(context, attrs, 0); } public TranslationView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onFinishInflate() { super.onFinishInflate(); if (getChildCount() != 2) { throw new IllegalStateException("only and should contain two child view"); } mTranslationView = getChildAt(1); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.d(TAG, "onMeasure"); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); mTranslationView.layout(0, -mTranslationView.getHeight(), mTranslationView.getWidth(), 0); } @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (mIsShow && child == mTranslationView) { canvas.drawColor(mShadowColor); } return super.drawChild(canvas, child, drawingTime); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_DOWN: { if (mIsShow && inShadow(ev)) { hide(); return true; } } } return super.onInterceptTouchEvent(ev); } private boolean inShadow(MotionEvent ev) { float x = ev.getX(); float y = ev.getY(); final float leftEdge = mTranslationView.getX(); final float rightEdge = leftEdge + mTranslationView.getWidth(); final float topEdge = mTranslationView.getHeight(); final float bottomEdge = getHeight() + topEdge; return x > leftEdge && x < rightEdge && y > topEdge && y < bottomEdge; } public void show() { if (!mIsShow) { mIsShow = true; if (mShowAni == null) { mShowAni = ObjectAnimator.ofFloat(mTranslationView, "translationY", mTranslationView.getTranslationY(), mTranslationView.getHeight()); mShowAni.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); invalidate(); } }); } mShowAni.start(); } } public void hide() { if (mIsShow) { mIsShow = false; if (mHideAni == null) { mHideAni = ObjectAnimator.ofFloat(mTranslationView, "translationY", mTranslationView.getTranslationY(), -mTranslationView.getHeight()); mHideAni.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); invalidate(); } }); } mHideAni.start(); } } public void setShadowColor(@ColorInt int color) { mShadowColor = color; }}
勘误:之前写这个小控件的时候,代码是有些问题的,虽然有点歪打正着。当初写这个控件的时候控件的坐标计算都是按照绝对坐标去思考的,但其实 translationY 是相对原坐标移动了多少的一个相对概念,虽然之前也已经了解了相关概念,没想到写的时候还是犯了错误。这次因为别的需要,扩展功能的时候才发现错误。
2017/6/1更新:新增其他方向的滑动效果。
public class TranslationView extends FrameLayout { public static final String START = "start"; public static final String END = "end"; public static final String TOP = "top"; public static final String BOTTOM = "bottom"; private static final String TAG = "TranslationView"; private static final int DEFAULT_COLOR = 0x50000000; private String mDirection = TOP; private int mShadowColor = DEFAULT_COLOR; private int mW; private int mH; private boolean mIsShow = false; private View mTranslationView; private ObjectAnimator mShowAni; private ObjectAnimator mHideAni; public TranslationView(Context context) { this(context, null); } public TranslationView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TranslationView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (attrs == null) { return; } TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TranslationView); mDirection = a.getString(R.styleable.TranslationView_direction); if (TextUtils.isEmpty(mDirection)) { mDirection = TOP; } a.recycle(); } @Override protected void onFinishInflate() { super.onFinishInflate(); if (getChildCount() != 2) { throw new IllegalStateException("only and should contain two child view"); } mTranslationView = getChildAt(1); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mW = w; mH = h; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); switch (mDirection) { case TOP: mTranslationView.layout(0, -mTranslationView.getHeight(), mTranslationView.getWidth(), 0); break; case BOTTOM: mTranslationView.layout(0, mH, mTranslationView.getWidth(), mH + mTranslationView.getHeight()); break; case START: mTranslationView.layout(-mTranslationView.getWidth(), 0, 0, mTranslationView.getHeight()); break; case END: mTranslationView.layout(mW, 0, mW + mTranslationView.getWidth(), mTranslationView.getHeight()); break; default: break; } } @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (mIsShow && child == mTranslationView) { canvas.drawColor(mShadowColor); } return super.drawChild(canvas, child, drawingTime); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_DOWN: { if (mIsShow && !inTranslationView(ev)) { hide(); return true; } } } return super.onInterceptTouchEvent(ev); } /** * 在内容区域中 * * @param ev * @return */ private boolean inTranslationView(MotionEvent ev) { float x = ev.getX(); float y = ev.getY(); final float leftEdge = mTranslationView.getX(); final float rightEdge = leftEdge + mTranslationView.getWidth(); final float topEdge = mTranslationView.getY(); final float bottomEdge = mTranslationView.getHeight() + topEdge; return x > leftEdge && x < rightEdge && y > topEdge && y < bottomEdge; } public void show() { if (!mIsShow) { mIsShow = true; if (mShowAni == null) { switch (mDirection) { case TOP: mShowAni = ObjectAnimator.ofFloat(mTranslationView, "translationY", 0, mTranslationView.getHeight()); break; case BOTTOM: mShowAni = ObjectAnimator.ofFloat(mTranslationView, "translationY", 0, -mTranslationView.getHeight()); break; case START: mShowAni = ObjectAnimator.ofFloat(mTranslationView, "translationX", 0, mTranslationView.getWidth()); break; case END: mShowAni = ObjectAnimator.ofFloat(mTranslationView, "translationX", 0, -mTranslationView.getWidth()); break; default: break; } mShowAni.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); invalidate(); } }); } mShowAni.start(); } } public void hide() { if (mIsShow) { mIsShow = false; if (mHideAni == null) { switch (mDirection) { case TOP: case BOTTOM: mHideAni = ObjectAnimator.ofFloat(mTranslationView, "translationY", mTranslationView.getTranslationY(), 0); break; case START: case END: mHideAni = ObjectAnimator.ofFloat(mTranslationView, "translationX", mTranslationView.getTranslationX(), 0); break; } mHideAni.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); invalidate(); } }); } mHideAni.start(); } } public void setShadowColor(@ColorInt int color) { mShadowColor = color; }}
效果图如下:
0 0
- 一个可以在界面顶部展现的自定义 View
- 在界面顶部滑动展开的自定义FrameLayout
- 自定义顶部标题栏的view
- 点击list,可以新增加一个自定义view的效果
- 一个简单的自定义View,可以显示上图下字
- Android自定义可以在文字上方显示备注的View
- 用xib自定义 可以在xib中使用的view
- Android -- 固定在ScrollView顶部的View
- TabActivity导航栏自定义并显示在界面顶部
- 自定义View-->实现顶部Topbar的简单UI模板
- 自定义View----带进度的返回顶部按钮
- 在listview中实现一个可以悬浮在listview顶部且可以被下一个titleBar推动并取代顶部titleBar
- 自定义View的界面和行为
- 实现登录界面的自定义view
- 高级界面之自定义View的使用
- 自定义View-获取界面的rootview
- 自定义View--可以拖曳的GridView
- 你也可以自己写一个可爱 & 小资风格的Android加载等待自定义View
- LCD主流显示接口介绍
- 全景虚拟漫游实现(three.js)
- RCNN学习笔记(2):R-CNN
- 秘鲁主流在线支付方式SafetyPay
- Android中HorizontalScrollView的使用总结
- 一个可以在界面顶部展现的自定义 View
- 十大经典排序算法的 JavaScript 实现
- java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用
- HDU 4824 Disk Schedule
- JAVA字符串常用api
- LD_LIBRARY_PATH这个环境变量的内容
- encoder-decoder
- 001 - JS 如何判断滚动条是否滚到底部
- PHP自定义输出日志到文件