打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
android中角标的实现

    如下图,角标在移动设备中是比较常见的ui元素。各种“最新”、“vip”、“最热”之类的层出不穷。

   

   在展现上最简单的做法是让ui同学ps一张角标图片输入“最新”、“vip”、“最热”等盖在要特别醒目提醒的控件上面即可。当然偷懒是没有一劳永逸的做法的,图片实现带文字的角标在当下android设备如此繁荣的情形下,码工们必然会为千奇百怪的适配而劳碌成大牛的,如果频繁更换图片中的文字ui设计师也会烦滴。
    下文探讨第一种角标的代码实现方式,其他三种还有比较少见的右下角、左下角的角标也可以照着做了。
   把第一种角标

直观化卸妆,那么她是这样的
       

   而这个图形我们可以看作是一个小长方形旋转某个角度后,底边两点刚好和大长方形左边和顶边链接叠加所成的直角三角形。

   在android中TextView、LinearLayout是方形的控件。那么,如果我们用TextView替代小长方形、LinearLayout替代大长方形,在TextView靠顶部左对齐的情况下,由下图看到这个几何图形可从A->B->C变换而成。

  



   最终的图形那么是

  

  其中点d坐标即是TextView的位移点,而∠bah则是TextView反方向旋转的角度。

  剩下的就是中学几何计算了。忘了吧!我们复习下要用到的公式:

  sinA=对边/斜边

  cosA=邻边/斜边

  A角度=arcsinA/π*180°

  勾股定理 c^2=a^2+b^2

  好了,这几个公式够我们用了。

 

   根据UI同学的设计图,那么eb、ea两三角边是可以量出来滴(需要注意的是eb不一定=ea)。

通过垂直三角形、长方形的各种垂直、平衡关系

可得∠bah=∠ebf=∠deg=∠gad

ab=√(eb^2+ab^2)

ef=sin(∠ebf)*eb

dg=sin(∠gad)*da=sin(∠ebf)*ef

ga=cos(∠gad)*da=cos(∠ebf)*ef

eg=ea-ga

  到这里就是怎么在代码中对TextView做移动和旋转动作了。由于多次尝试直接对Canvas做移动旋转失败,所以我采用Animation来完成这一系列动作。下面是实现控件的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.droidwolf.superscript;
import android.content.Context;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.TextView;
public class SuperscriptView extends TextView {
    private float mDegress,mX,mY;
    private int mHeight,mWidth;
     
    public SuperscriptView(Context context) {
        super(context);
        init(context, null);
    }
    public SuperscriptView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }
    public SuperscriptView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs);
    }
    @Override
    public void setVisibility(int visibility) {
        setAnimation(visibility == View.VISIBLE? mAnimation: null);
        super.setVisibility(visibility);
    }
    private void init(Context context, AttributeSet attrs) {
        DisplayMetrics dm = getResources().getDisplayMetrics();
        int topEdge = Math.round(TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 41.333f, dm));
        int  leftEdge= Math.round(TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 41.333f, dm));
        calc(leftEdge, topEdge);
        mAnimation.setFillBefore(true);
        mAnimation.setFillAfter(true);
        mAnimation.setFillEnabled(true);
        startAnimation(mAnimation);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mHeight < 1 || mWidth < 1) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        else {
            setMeasuredDimension(mWidth, mHeight);
        }
    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        int vi= getVisibility();
        setAnimation(null);
        setVisibility(vi);
    }
     
    private void calc(int leftEdge, int topEdge) {
        final double ab = Math.sqrt(Math.pow(topEdge, 2d)+ Math.pow(leftEdge, 2d));
        final double sinB = leftEdge / ab;
        mDegress = -(float) Math.toDegrees(Math.asin(sinB));
        // ef=da=sin(∠ebf)*eb
        mHeight = Math.round((float) (sinB * topEdge));
        // de=sin(∠ead)*ea=sin(∠ebf)*ea
        final double de = sinB * leftEdge;
        // dg=cos(∠ead)*de=cos(∠ebf)*de
        mX = -(float) ((topEdge / ab) * de);
        // eg==sin(∠edg)*de=sin(∠ebf)*de
        mY = (float) (sinB * de);
        mWidth = Math.round((float) ab);
    }
    private Animation mAnimation = new Animation() {
        protected void applyTransformation(float interpolatedTime,Transformation t) {
            if (mHeight < 1 || mWidth < 1) {
                return;
            }
            Matrix tran = t.getMatrix();
            tran.setTranslate(mX, mY);
            tran.postRotate(mDegress, mX, mY);
        }
    };
}

 

   实现demo。我还实现了第一张图的另外三种角标到一个控件,请移步到我的bitbucket

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android自定义查看更多TextView
Android下拉刷新功能实现过程详解
玩转Android 之 TextView常用特效
Android自定义组合控件的实现
android 动态创建控件并设置布局
android自定义view 兑现TextView 中文粗体
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服