1 简介
BadgeView继承自TextView,可用于消息提醒,如微信的消息提醒数目的显示。
源码 https://github.com/stefanjauker/BadgeView
2 源码
1 知识点
1 继承textview时构造函数的attrs属性
public BadgeView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
}
2 初始化
private void init() {
// 用代码new时,getLayoutParams()为null,因此要设置其位置。或者类型不匹配也要设置
if (!(getLayoutParams() instanceof LayoutParams)) {
// 类型 android.widget.FrameLayout.LayoutParams,因为badgeview父就是FrameLayout
LayoutParams layoutParams =
new LayoutParams(
android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.RIGHT | Gravity.TOP);
setLayoutParams(layoutParams);
}
// set default font
setTextColor(Color.WHITE);
setTypeface(Typeface.DEFAULT_BOLD);
setTextSize(TypedValue.COMPLEX_UNIT_SP, 11);
setPadding(dip2Px(5), dip2Px(1), dip2Px(5), dip2Px(1));
// set default background --- down
setBackground(9, Color.parseColor("#d3321b"));
// default values --- down
setHideOnNull(true);
// --- down
setBadgeCount(0);
}
setBackground函数
public void setBackground(int dipRadius, int badgeColor) {
int radius = dip2Px(dipRadius);
float[] radiusArray = new float[] { radius, radius, radius, radius, radius, radius, radius, radius };
/** RoundRectShape constructor. Specifies an outer (round)rect and an optional inner (round)rect.
outerRadii: An array of 8 radius values, for the outer roundrect. The first two floats are for the top-left corner (remaining pairs correspond clockwise). For no rounded corners on the outer rectangle, pass null.
inset: A RectF that specifies the distance from the inner rect to each side of the outer rect. For no inner, pass null.
innerRadii: An array of 8 radius values, for the inner roundrect. The first two floats are for the top-left corner (remaining pairs correspond clockwise). For no rounded corners on the inner rectangle, pass null. If inset parameter is null, this parameter is ignored.
*/
// 创建一个圆角矩形的形状,dipRadius如果够大了就会近圆的形状了
RoundRectShape roundRect = new RoundRectShape(radiusArray, null, null);
// 创建ShapeDrawable,利用的是上面创建的shape
ShapeDrawable bgDrawable = new ShapeDrawable(roundRect);
// 设置画笔颜色
bgDrawable.getPaint().setColor(badgeColor);
// 设置背景为ShapeDrawable
setBackgroundDrawable(bgDrawable);
}
位置的设置
public void setBadgeGravity(int gravity) {
FrameLayout.LayoutParams params = (LayoutParams) getLayoutParams();
params.gravity = gravity;
setLayoutParams(params);
}
text数字的递变
public void incrementBadgeCount(int increment) {
Integer count = getBadgeCount();
if (count == null) {
setBadgeCount(increment);
} else {
setBadgeCount(increment + count);
}
}
public void setBadgeMargin方法等等边距
3 设置所指示的目标view
/*
* Attach the BadgeView to the target view
*
* @param target the view to attach the BadgeView
*/
public void setTargetView(View target) {
if (getParent() != null) { // 确保只有一个目标view
((ViewGroup) getParent()).removeView(this);
}
if (target == null) {
return;
}
if (target.getParent() instanceof FrameLayout) {
// 因为对于FrameLayout,layoutParams在初始化的时候已经设置好了
((FrameLayout) target.getParent()).addView(this);
} else if (target.getParent() instanceof ViewGroup) {
// 添加一个FrameLayout去将目标view和badgeview封装起来
// use a new Framelayout container for adding badge
ViewGroup parentContainer = (ViewGroup) target.getParent();
int groupIndex = parentContainer.indexOfChild(target);
parentContainer.removeView(target); // 移除目标view
FrameLayout badgeContainer = new FrameLayout(getContext());
ViewGroup.LayoutParams parentLayoutParams = target.getLayoutParams();
// 设置参数
badgeContainer.setLayoutParams(parentLayoutParams);
target.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
// 将新创建的FrameLayout添加到刚刚删除了的目标view的位置
parentContainer.addView(badgeContainer, groupIndex, parentLayoutParams);
badgeContainer.addView(target); // 目标view新位置
badgeContainer.addView(this);
} else if (target.getParent() == null) {
Log.e(getClass().getSimpleName(), "ParentView is needed");
}
}
2 源码例子
1 主Activity
// Set up the action bar. 利用actionbar的导航功能
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) { // 设置actionbar的当前tab
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
Tab tab = actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this);
actionBar.addTab(tab);
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager. 点击tab时的监听回调
mViewPager.setCurrentItem(tab.getPosition());
}
2 ListFragment extends android.support.v4.app.ListFragment
继承ListFragment后,只需要下面代码即可
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ListAdapter(getActivity()));
}
TextView的几个系统属性设置
android:id=”@android:id/text1”
android:minHeight=”?android:attr/listPreferredItemHeight”
android:textAppearance=”?android:attr/textAppearanceLarge”
3
设置背景为图片资源而不是默认的圆角矩形
backgroundDrawableBadge.setBackgroundResource(R.drawable.badge_blue);
设置圆角的大小和颜色backgroundShapeBadge.setBackground(12, Color.parseColor(“#9b2eef”));
风格样式textStyleBadge.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.ITALIC));
Sets the typeface and style in which the text should be displayed
阴影吧textStyleBadge.setShadowLayer(2, -1, -1, Color.GREEN);
解释:Gives the text a shadow of the specified radius and color, the specified distance from its normal position。
setShadowLayer(float radius, float dx, float dy, int color)