Android自定义View实现TextView右上角动态红点

1 下载量 189 浏览量 更新于2024-09-04 收藏 107KB PDF 举报
"Android开发中实现TextView右上角动态追加圆形红点的实例代码" 在Android应用开发中,有时我们需要在TextView的右上角显示一个动态的圆形红点,通常用于表示有未读消息或者更新。这篇内容将介绍如何通过自定义View来实现这一功能。需求是让这个红点能够随着TextView中的文本内容变化而动态调整位置。 首先,我们需要创建一个新的自定义View,让它继承自View类。以下是一个简单的自定义View的初始化: ```java public class MyViewAndCircle extends View { public MyViewAndCircle(Context context) { this(context, null); } public MyViewAndCircle(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyViewAndCircle(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } } ``` 接下来,我们需要定义一些属性来控制TextView的显示,例如文本内容、字体大小和颜色。这些属性可以通过XML声明式的方式添加到自定义View中: ```xml <declare-styleable name="CustomMyViewTitle"> <attr name="titleTextview" format="string"/> <attr name="titleSize" format="dimension"/> <attr name="titleColor" format="color"/> </declare-styleable> ``` 有了这些基础设置,我们可以在自定义View中绘制文本和红点。在`onDraw()`方法中,我们可以先绘制文本,再根据文本的位置和尺寸画出红点: ```java @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取自定义属性值 String titleText = ...; // 获取titleTextview属性值 float textSize = ...; // 获取titleSize属性值 int titleColor = ...; // 获取titleColor属性值 // 绘制文本 Paint paint = new Paint(); paint.setColor(titleColor); paint.setTextSize(textSize); paint.setTextAlign(Paint.Align.LEFT); float textWidth = paint.measureText(titleText); canvas.drawText(titleText, 0, textSize / 2f + 1, paint); // 计算红点的位置 float dotX = textWidth + padding; float dotY = textSize / 2f; // 绘制红点 paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(dotX, dotY, dotRadius, paint); } ``` 这里的关键在于计算红点的位置,使其位于文本的右上角。`dotX`是红点的横坐标,等于文本宽度加上一定的内边距;`dotY`是红点的纵坐标,通常设置为文本高度的一半。 最后,为了使这个自定义View能被XML布局文件引用,我们需要在布局文件中声明并设置属性: ```xml <com.example.MyViewAndCircle android:layout_width="wrap_content" android:layout_height="wrap_content" app:titleTextview="动态文本" app:titleSize="16sp" app:titleColor="@android:color/black" /> ``` 通过这种方式,我们可以在Android应用中轻松实现TextView右上角动态追加的圆形红点,并且可以根据需要自定义文本属性和红点样式。这个实例代码适用于那些希望在不改变原有布局结构的情况下,快速实现类似功能的开发者。
2019-09-23 上传
目录介绍01.该库介绍02.效果展示03.如何使用04.注意要点05.优化问题06.部分代码逻辑01.该库介绍自定义红点控件,不用修改之前的代码,完全解耦,既可以设置红点数字控件,使用十分方便。网上看到有些案例是继承View,然后去测量和绘制红点的相关操作,此案例则不需要这样,继承TextView也可以完成设置红点功能。可以支持设置在TextView,Button,LinearLayout,RelativeLayout,TabLayout等等控件上……大概的原理是:继承TextView,然后设置LayoutParams,设置内容,设置Background等等属性,然后在通过addView添加到父控件中。02.效果展示03.如何使用如何引用implementation 'cn.yc:YCRedDotViewLib:1.0.3'如下所示//创建红点View YCRedDotView ycRedDotView = new YCRedDotView(this); //设置依附的View ycRedDotView.setTargetView(tv1); //设置红点的数字 ycRedDotView.setBadgeCount(10); //设置红点位置 ycRedDotView.setRedHotViewGravity(Gravity.END); //获取小红点的数量 int count = ycRedDotView.getBadgeCount(); //如果是设置小红点,不设置数字,则可以用这个,设置属性是直径 ycRedDotView.setBadgeView(10); //设置margin ycRedDotView.setBadgeMargin(0,10,20,0);04.注意要点如果设置数字大于99,则会显示“99 ”。如果设置为0,则不可见。05.优化问题相比网上一些案例,该库不需要做测量绘制方面操作,代码十分简洁,但却也可以完成你需要的功能。有些红点View,需要你在布局中设置,要是很多地方有设置红点操作,则比较麻烦。而该案例不需要改变你之前的任何代码,只是需要按照步骤即可设置红点。设置红点view到你的控件的逻辑操作代码如下所示。如果控件父布局是帧布局,则直接添加;如果控件父布局是ViewGroup,则创建一个帧布局,然后添加红点/**  * 设置红点依附的view  * @param view                  view  */ public void setTargetView(View view){     if (getParent() != null) {         ((ViewGroup) getParent()).removeView(this);     }     if (view == null) {         return;     }     if(view.getParent() instanceof FrameLayout){         ((FrameLayout) view.getParent()).addView(this);     }else if(view.getParent() instanceof ViewGroup){         ViewGroup parentContainer = (ViewGroup) view.getParent();         int groupIndex = parentContainer.indexOfChild(view);         parentContainer.removeView(view);         FrameLayout badgeContainer = new FrameLayout(getContext());         ViewGroup.LayoutParams parentLayoutParams = view.getLayoutParams();         badgeContainer.setLayoutParams(parentLayoutParams);         view.setLayoutParams(new ViewGroup.LayoutParams(                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));         parentContainer.addView(badgeContainer, groupIndex, parentLayoutParams);         badgeContainer.addView(view);         badgeContainer.addView(this);     }else {         Log.e(getClass().getSimpleName(), "ParentView is must needed");     } }