Android——Label样式

样式:
这里写图片描述

使用:

        final LabelView myLabel = new LabelView(this);
        myLabel.setText("hq");
        myLabel.setBackgroundColor(0xffE91E63);
//      参数1:目标view
//      参数2:徽章距离view顶角的距离
//      参数3:徽章的位置
        myLabel.setTargetView(findViewById(R.id.myImg), 0, LabelView.Gravity.LEFT_TOP);

        final LabelView myLabel1 = new LabelView(this);
        myLabel1.setText("");
        myLabel1.setBackgroundColor(0xffE91E63);
        myLabel1.setTargetView(findViewById(R.id.myImg1), 0, LabelView.Gravity.RIGHT_TOP);

        final LabelView myLabel2 = new LabelView(this);
        myLabel2.setText("hq");
        myLabel2.setBackgroundColor(0xffE91E63);
        myLabel2.setTargetView(findViewById(R.id.myImg2), 5, LabelView.Gravity.RIGHT_TOP);

源码:

/*
 * Copyright (C) 2011 The Android Open Source Project
 * Copyright 2014 linger1216
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.lid.lib;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.concurrent.atomic.AtomicInteger;

public class LabelView extends TextView {

    private float _offsetx;
    private float _offsety;
    private float _anchorx;
    private float _anchory;
    private float _angel;
    private int _labelViewContainerID;
    private Animation _animation = new Animation() {
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            Matrix tran = t.getMatrix();
            tran.postTranslate(_offsetx, _offsety);
            tran.postRotate(_angel, _anchorx, _anchory);
        }
    };

    public enum Gravity {
        LEFT_TOP, RIGHT_TOP
    }

    public LabelView(Context context) {
        this(context, null);
    }

    public LabelView(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

    public LabelView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        init();

        _animation.setFillBefore(true);
        _animation.setFillAfter(true);
        _animation.setFillEnabled(true);

    }


    private void init() {

        if (!(getLayoutParams() instanceof ViewGroup.LayoutParams)) {
            LayoutParams layoutParams =
                    new LayoutParams(
                            ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.WRAP_CONTENT);
            setLayoutParams(layoutParams);
        }

        // the default value
        //setPadding(dip2Px(40), dip2Px(2), dip2Px(40), dip2Px(2));
        _labelViewContainerID = -1;

        setGravity(android.view.Gravity.CENTER);
        setTextColor(Color.WHITE);
        setTypeface(Typeface.DEFAULT_BOLD);
        setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
        setBackgroundColor(Color.BLUE);
    }

    public void setTargetView(View target, int distance, Gravity gravity) {

        if (!replaceLayout(target)) {
            return;
        }

        final int d = dip2Px(distance);
        final Gravity g = gravity;
        final View v = target;

        ViewTreeObserver vto = getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
                calcOffset(getMeasuredWidth(), d, g, v.getMeasuredWidth(), false);
            }
        });

    }


    public void setTargetViewInBaseAdapter(View target, int targetWidth, int distance, Gravity gravity) {
        if (!replaceLayout(target)) {
            return;
        }
        //measure(0, 0);
        //calcOffset(getMeasuredWidth(), distance, gravity, targetWidth, true);
        calcOffset(dip2Px(targetWidth), distance, gravity, targetWidth, true);
    }

    public void remove() {
        if (getParent() == null || _labelViewContainerID == -1) {
            return;
        }

        ViewGroup frameContainer = (ViewGroup) getParent();
        assert (frameContainer.getChildCount() == 2);
        View target = frameContainer.getChildAt(0);

        ViewGroup parentContainer = (ViewGroup) frameContainer.getParent();
        int groupIndex = parentContainer.indexOfChild(frameContainer);
        if (frameContainer.getParent() instanceof RelativeLayout) {
            for (int i = 0; i < parentContainer.getChildCount(); i++) {
                if (i == groupIndex) {
                    continue;
                }
                View view = parentContainer.getChildAt(i);
                RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) view.getLayoutParams();
                for (int j = 0; j < para.getRules().length; j++) {
                    if (para.getRules()[j] == _labelViewContainerID) {
                        para.getRules()[j] = target.getId();
                    }
                }
                view.setLayoutParams(para);
            }
        }

        ViewGroup.LayoutParams frameLayoutParam = frameContainer.getLayoutParams();
        target.setLayoutParams(frameLayoutParam);
        parentContainer.removeViewAt(groupIndex);
        frameContainer.removeView(target);
        frameContainer.removeView(this);
        parentContainer.addView(target,groupIndex);
        _labelViewContainerID = -1;
    }

    private boolean replaceLayout(View target) {
        if (getParent() != null || target == null || target.getParent() == null || _labelViewContainerID != -1) {
            return false;
        }

        ViewGroup parentContainer = (ViewGroup) target.getParent();

        if (target.getParent() instanceof FrameLayout) {
            ((FrameLayout) target.getParent()).addView(this);
        } else if (target.getParent() instanceof ViewGroup) {

            int groupIndex = parentContainer.indexOfChild(target);
            _labelViewContainerID = generateViewId();

            // relativeLayout need copy rule
            if (target.getParent() instanceof RelativeLayout) {
                for (int i = 0; i < parentContainer.getChildCount(); i++) {
                    if (i == groupIndex) {
                        continue;
                    }
                    View view = parentContainer.getChildAt(i);
                    RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) view.getLayoutParams();
                    for (int j = 0; j < para.getRules().length; j++) {
                        if (para.getRules()[j] == target.getId()) {
                            para.getRules()[j] = _labelViewContainerID;
                        }
                    }
                    view.setLayoutParams(para);
                }
            }
            parentContainer.removeView(target);

            // new dummy layout
            FrameLayout labelViewContainer = new FrameLayout(getContext());
            ViewGroup.LayoutParams targetLayoutParam = target.getLayoutParams();
            labelViewContainer.setLayoutParams(targetLayoutParam);
            target.setLayoutParams(new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

            // add target and label in dummy layout
            labelViewContainer.addView(target);
            labelViewContainer.addView(this);
            labelViewContainer.setId(_labelViewContainerID);

            // add dummy layout in parent container
            parentContainer.addView(labelViewContainer, groupIndex, targetLayoutParam);
        }
        return true;
    }

    private void calcOffset(int labelWidth, int distance, Gravity gravity, int targetWidth, boolean isDP) {

        int d = dip2Px(distance);
        int tw = isDP ? dip2Px(targetWidth) : targetWidth;

        float edge = (float) ((labelWidth - 2 * d) / (2 * 1.414));
        if (gravity == Gravity.LEFT_TOP) {
            _anchorx = -edge;
            _offsetx = _anchorx;
            _angel = -45;
        } else if (gravity == Gravity.RIGHT_TOP) {
            _offsetx = tw + edge - labelWidth;
            _anchorx = tw + edge;
            _angel = 45;
        }

        _anchory = (float) (1.414 * d + edge);
        _offsety = _anchory;

        clearAnimation();
        startAnimation(_animation);
    }

    private int dip2Px(float dip) {
        return (int) (dip * getContext().getResources().getDisplayMetrics().density + 0.5f);
    }

    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);

    public static int generateViewId() {
        for (; ; ) {
            final int result = sNextGeneratedId.get();
            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
            int newValue = result + 1;
            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
            if (sNextGeneratedId.compareAndSet(result, newValue)) {
                return result;
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值