转载请注明出处:王亟亟的大牛之路
一个自定义TextView可实现各种控件右上,左上等位置附带便签实现。
项目结构:
运行效果:
只需要一个类就可以完成以上实现
LabelView
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);
}
@SuppressLint("NewApi")
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;
}
@SuppressLint("NewApi")
private boolean replaceLayout(View target) {
if (getParent() !=