Android 自定义消息右上角的数字提示或红点(类似微信或QQ的未读消息提示)       支持自由定制外观、拖拽消除的MaterialDesign风格Android BadgeView,自定义消息右上角的数字提示或红点(类似微信或QQ的未读消息提示)实现消息数量大于0时显示具体消息数量,最大显示99,大于99设置99+效果 一.效果图:       二.添加依赖快速实现: 1.添加依赖:(也可以不添加依赖直接将自定义类写到自己的项目中) 2.代码实现: 3.方法说明:    可以参考:https://github.com/qstumn/BadgeView 三.自定义BadgeView: 1.主函数代码: 2.主函数布局: 3.相关属性: dimens.xml: string.xml: shape_round_rect.xml: 4.实现接口Badge.java: 5.自定义动画BadgeAnimator.java: 6.dp、px转换工具类DisplayUtil.java: 7.数学计算工具类MathUtil.java: 8.自定义QQ消息类QBadgeView.java: 9.模拟数据类: 四.实现QQ或微信聊天列表的消息提醒的话可以往下看: 1.ListViewActivity.java: 2.布局activity_list_view.xml: 3.适配器布局item_view.xml   4.使用RecyclerView实现QQ或微信聊天列表消息数量显示: RecyclerViewActivity.java:      


 
implementation 'q.rorbin:badgeview:1.1.3' 
new QBadgeView(context).bindTarget(textview).setBadgeNumber(6);
 
code 
说明 
 
setBadgeNumber 
设置Badge数字 
 
setBadgeText 
设置Badge文本 
 
setBadgeTextSize 
设置文本字体大小 
 
setBadgeTextColor 
设置文本颜色 
 
setExactMode 
设置是否显示精确模式数值 
 
setBadgeGravity 
设置Badge相对于TargetView的位置 
 
setGravityOffset 
设置外边距 
 
setBadgePadding 
设置内边距 
 
setBadgeBackgroundColor 
设置背景色 
 
setBadgeBackground 
设置背景图片 
 
setShowShadow 
设置是否显示阴影 
 
setOnDragStateChangedListener 
打开拖拽消除模式并设置监听 
 
stroke 
描边 
 
hide 
隐藏Badge 
 
import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.AbsListView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.GridView; import android.widget.ImageView; import android.widget.RadioButton; import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.Switch; import android.widget.TextView; import com.example.m1571.myapplication.badgeview.Badge; import com.example.m1571.myapplication.badgeview.QBadgeView;  import java.util.ArrayList; import java.util.List;  //import q.rorbin.badgeview.QBadgeView;  public class MainActivity extends AppCompatActivity {     TextView textview, tv_offsetx, tv_padding, tv_offsety, tv_numbersize, tv_dragstate;     EditText et_badgenumber, et_badgetext;     ImageView imageview, iv_badgecolor, iv_numbercolor;     Button button, btn_animation;     List<RadioButton> radioButtons = new ArrayList<>();     CompoundButton lastRadioButton;     SeekBar seekBar_offsetx, seekBar_padding, seekBar_offsety, seekBar_numbersize;     Switch swicth_exact, swicth_draggable, swicth_shadow;      List<Badge> badges;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         initView();         initListener();         initBadge();         swicth_draggable.setChecked(true);     }     private void initBadge() {         badges = new ArrayList<>();         badges.add(new QBadgeView(this).bindTarget(textview).setBadgeNumber(5));         badges.add(new QBadgeView(this).bindTarget(imageview).setBadgeText("PNG").setBadgeTextColor(0x00000000)                 .setBadgeGravity(Gravity.BOTTOM | Gravity.END).setBadgeBackgroundColor(0xff03a9f4)                 .setBadgeBackground(getResources().getDrawable(R.drawable.shape_round_rect)));         badges.add(new QBadgeView(this).bindTarget(button).setBadgeText("新").setBadgeTextSize(13, true)                 .setBadgeBackgroundColor(0xffffeb3b).setBadgeTextColor(0xff000000)                 .stroke(0xff000000, 1, true));     }      private void initView() {         textview = (TextView) findViewById(R.id.textview);         tv_offsetx = (TextView) findViewById(R.id.tv_offsetx);         tv_offsety = (TextView) findViewById(R.id.tv_offsety);         tv_padding = (TextView) findViewById(R.id.tv_padding);         tv_numbersize = (TextView) findViewById(R.id.tv_numbersize);         tv_dragstate = (TextView) findViewById(R.id.tv_dragstate);         et_badgenumber = (EditText) findViewById(R.id.et_badgenumber);         et_badgetext = (EditText) findViewById(R.id.et_badgetext);         imageview = (ImageView) findViewById(R.id.imageview);         iv_badgecolor = (ImageView) findViewById(R.id.iv_badgecolor);         iv_numbercolor = (ImageView) findViewById(R.id.iv_numbercolor);         iv_numbercolor = (ImageView) findViewById(R.id.iv_numbercolor);         button = (Button) findViewById(R.id.button);         btn_animation = (Button) findViewById(R.id.btn_animation);         radioButtons.add((RadioButton) findViewById(R.id.rb_st));         radioButtons.add((RadioButton) findViewById(R.id.rb_sb));         RadioButton rb_et = (RadioButton) findViewById(R.id.rb_et);         lastRadioButton = rb_et;         radioButtons.add(rb_et);         radioButtons.add((RadioButton) findViewById(R.id.rb_eb));         radioButtons.add((RadioButton) findViewById(R.id.rb_ct));         radioButtons.add((RadioButton) findViewById(R.id.rb_ce));         radioButtons.add((RadioButton) findViewById(R.id.rb_cb));         radioButtons.add((RadioButton) findViewById(R.id.rb_cs));         radioButtons.add((RadioButton) findViewById(R.id.rb_c));         seekBar_offsetx = (SeekBar) findViewById(R.id.seekBar_offsetx);         seekBar_offsety = (SeekBar) findViewById(R.id.seekBar_offsety);         seekBar_padding = (SeekBar) findViewById(R.id.seekBar_padding);         seekBar_numbersize = (SeekBar) findViewById(R.id.seekBar_numbersize);         swicth_exact = (Switch) findViewById(R.id.swicth_exact);         swicth_draggable = (Switch) findViewById(R.id.swicth_draggable);         swicth_shadow = (Switch) findViewById(R.id.swicth_shadow);     }      private void initListener() {         CompoundButton.OnCheckedChangeListener checkedChangeListener = new CompoundButton.OnCheckedChangeListener() {             @Override             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                 if (!isChecked) {                     return;                 }                 if (lastRadioButton != null) {                     lastRadioButton.setChecked(false);                 }                 lastRadioButton = buttonView;                 for (Badge badge : badges) {                     switch (buttonView.getId()) {                         case R.id.rb_st:                             badge.setBadgeGravity(Gravity.START | Gravity.TOP);                             break;                         case R.id.rb_sb:                             badge.setBadgeGravity(Gravity.START | Gravity.BOTTOM);                             break;                         case R.id.rb_et:                             badge.setBadgeGravity(Gravity.END | Gravity.TOP);                             break;                         case R.id.rb_eb:                             badge.setBadgeGravity(Gravity.END | Gravity.BOTTOM);                             break;                         case R.id.rb_ct:                             badge.setBadgeGravity(Gravity.CENTER | Gravity.TOP);                             break;                         case R.id.rb_ce:                             badge.setBadgeGravity(Gravity.CENTER | Gravity.END);                             break;                         case R.id.rb_cb:                             badge.setBadgeGravity(Gravity.CENTER | Gravity.BOTTOM);                             break;                         case R.id.rb_cs:                             badge.setBadgeGravity(Gravity.CENTER | Gravity.START);                             break;                         case R.id.rb_c:                             badge.setBadgeGravity(Gravity.CENTER);                             break;                     }                 }             }         };         for (RadioButton rb : radioButtons) {             rb.setOnCheckedChangeListener(checkedChangeListener);         }         SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {             @Override             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {                 for (Badge badge : badges) {                     if (seekBar == seekBar_offsetx || seekBar == seekBar_offsety) {                         int x = seekBar_offsetx.getProgress();                         int y = seekBar_offsety.getProgress();                         tv_offsetx.setText("GravityOffsetX : " + x);                         tv_offsety.setText("GravityOffsetY : " + y);                         badge.setGravityOffset(x, y, true);                     } else if (seekBar == seekBar_padding) {                         tv_padding.setText("BadgePadding : " + progress);                         badge.setBadgePadding(progress, true);                     } else if (seekBar == seekBar_numbersize) {                         tv_numbersize.setText("TextSize : " + progress);                         badge.setBadgeTextSize(progress, true);                     }                 }             }              @Override             public void onStartTrackingTouch(SeekBar seekBar) {              }              @Override             public void onStopTrackingTouch(SeekBar seekBar) {              }         };         seekBar_offsetx.setOnSeekBarChangeListener(onSeekBarChangeListener);         seekBar_offsety.setOnSeekBarChangeListener(onSeekBarChangeListener);         seekBar_padding.setOnSeekBarChangeListener(onSeekBarChangeListener);         seekBar_numbersize.setOnSeekBarChangeListener(onSeekBarChangeListener);         View.OnClickListener onClickListener = new View.OnClickListener() {             @Override             public void onClick(View v) {                  if (v == iv_badgecolor) {                     selectorColor(new OnColorClickListener() {                         @Override                         public void onColorClick(int color) {                             iv_badgecolor.setBackgroundColor(color);                             for (Badge badge : badges) {                                 badge.setBadgeBackgroundColor(color);                             }                         }                     });                 } else if (v == iv_numbercolor) {                     selectorColor(new OnColorClickListener() {                         @Override                         public void onColorClick(int color) {                             iv_numbercolor.setBackgroundColor(color);                             for (Badge badge : badges) {                                 badge.setBadgeTextColor(color);                             }                         }                     });                 } else if (v == btn_animation) {                     for (Badge badge : badges) {                         badge.hide(true);                     }                 }             }         };         iv_badgecolor.setOnClickListener(onClickListener);         iv_numbercolor.setOnClickListener(onClickListener);         btn_animation.setOnClickListener(onClickListener);         class MyTextWatcher implements TextWatcher {             private EditText editText;              public MyTextWatcher(EditText editText) {                 this.editText = editText;             }              @Override             public void beforeTextChanged(CharSequence s, int start, int count, int after) {              }              @Override             public void onTextChanged(CharSequence s, int start, int before, int count) {                 try {                     for (Badge badge : badges) {                         if (editText == et_badgenumber) {                             int num = TextUtils.isEmpty(s) ? 0 : Integer.parseInt(s.toString());                             badge.setBadgeNumber(num);                         } else if (editText == et_badgetext) {                             badge.setBadgeText(s.toString());                         }                     }                 } catch (Exception e) {                     e.printStackTrace();                 }             }              @Override             public void afterTextChanged(Editable s) {              }         }          et_badgenumber.addTextChangedListener(new MyTextWatcher(et_badgenumber));         et_badgetext.addTextChangedListener(new MyTextWatcher(et_badgetext));         CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {             @Override             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                 for (Badge badge : badges) {                     if (buttonView == swicth_exact) {                         badge.setExactMode(isChecked);                     } else if (buttonView == swicth_draggable) {                         badge.setOnDragStateChangedListener(isChecked ?                                 new Badge.OnDragStateChangedListener() {                                     @Override                                     public void onDragStateChanged(int dragState, Badge badge, View targetView) {                                         switch (dragState) {                                             case STATE_START:                                                 tv_dragstate.setText("STATE_START");                                                 break;                                             case STATE_DRAGGING:                                                 tv_dragstate.setText("STATE_DRAGGING");                                                 break;                                             case STATE_DRAGGING_OUT_OF_RANGE:                                                 tv_dragstate.setText("STATE_DRAGGING_OUT_OF_RANGE");                                                 break;                                             case STATE_SUCCEED:                                                 tv_dragstate.setText("STATE_SUCCEED");                                                 break;                                             case STATE_CANCELED:                                                 tv_dragstate.setText("STATE_CANCELED");                                                 break;                                         }                                     }                                 } : null);                     } else if (buttonView == swicth_shadow) {                         badge.setShowShadow(isChecked);                     }                 }             }         };         swicth_exact.setOnCheckedChangeListener(onCheckedChangeListener);         swicth_draggable.setOnCheckedChangeListener(onCheckedChangeListener);         swicth_shadow.setOnCheckedChangeListener(onCheckedChangeListener);     }      private void selectorColor(final OnColorClickListener l) {         final AlertDialog dialog = new AlertDialog.Builder(this).create();         GridView gv = new GridView(this);         gv.setNumColumns(4);         gv.setAdapter(new BaseAdapter() {             int[] colors = new int[]{Color.TRANSPARENT, 0xffffffff, 0xff000000, 0xffe51c23, 0xffE84E40, 0xff9c27b0, 0xff673ab7,                     0xff3f51b5, 0xff5677fc, 0xff03a9f4, 0xff00bcd4, 0xff009688, 0xff259b24, 0xff8bc34a, 0xffcddc39,                     0xffffeb3b, 0xffffc107, 0xffff9800, 0xffff5722, 0xff795548};              @Override             public int getCount() {                 return colors.length;             }              @Override             public Object getItem(int position) {                 return colors[position];             }              @Override             public long getItemId(int position) {                 return position;             }              @Override             public View getView(final int position, View convertView, ViewGroup parent) {                 View v = new View(MainActivity.this);                 v.setBackgroundColor(colors[position]);                 v.setOnClickListener(new View.OnClickListener() {                     @Override                     public void onClick(View v) {                         l.onColorClick(colors[position]);                         dialog.dismiss();                     }                 });                 DisplayMetrics dm = new DisplayMetrics();                 WindowManager wm = (WindowManager) MainActivity.this                         .getSystemService(Context.WINDOW_SERVICE);                 wm.getDefaultDisplay().getMetrics(dm);                 GridView.LayoutParams lp = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,                         (int) (dm.widthPixels / 5f));                 v.setLayoutParams(lp);                 return v;             }         });         dialog.setView(gv);         dialog.show();         dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0x33FFFFFF));     }      interface OnColorClickListener {         void onColorClick(int color);     } }  
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"     xmlns:tools="https://schemas.android.com/tools"     android:id="@+id/activity_main"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:background="#555555"     android:orientation="vertical"     android:paddingBottom="@dimen/activity_vertical_margin"     android:paddingLeft="@dimen/activity_horizontal_margin"     android:paddingRight="@dimen/activity_horizontal_margin"     android:paddingTop="@dimen/activity_vertical_margin"     tools:context=".MainActivity">      <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_marginBottom="15dp"         android:gravity="center_vertical"         android:orientation="horizontal">          <TextView             android:id="@+id/textview"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:padding="20dp"             android:text="@string/textview"             android:textColor="#FFFFFF"             android:textSize="18sp"             android:textStyle="bold" />          <ImageView             android:id="@+id/imageview"             android:layout_width="0dp"             android:layout_height="60dp"             android:layout_weight="1"             android:src="@drawable/show" />          <Button             android:id="@+id/button"             android:layout_marginLeft="5dp"             android:background="@drawable/g"             android:layout_width="0dp"             android:layout_height="60dp"             android:layout_weight="1"             android:text="@string/button" />      </LinearLayout>      <View         android:layout_width="match_parent"         android:layout_height="1px"         android:layout_marginBottom="20dp"         android:background="#FFFFFF" />      <ScrollView         android:layout_width="match_parent"         android:layout_height="wrap_content">          <LinearLayout             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:orientation="vertical">              <RelativeLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_marginBottom="10dp">                  <TextView                     android:id="@+id/tv_gravity_tips"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:text="Gravity : "                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_st"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/tv_gravity_tips"                     android:text="Start | Top"                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_sb"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/tv_gravity_tips"                     android:layout_marginLeft="5dp"                     android:layout_toRightOf="@+id/rb_st"                     android:text="Start | Bottom"                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_et"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/tv_gravity_tips"                     android:layout_marginLeft="5dp"                     android:layout_toRightOf="@+id/rb_sb"                     android:checked="true"                     android:text="End | Top"                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_eb"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/rb_st"                     android:text="End | Bottom"                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_ct"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/rb_st"                     android:layout_marginLeft="5dp"                     android:layout_toRightOf="@+id/rb_eb"                     android:text="Center | Top"                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_ce"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/rb_st"                     android:layout_marginLeft="5dp"                     android:layout_toRightOf="@+id/rb_ct"                     android:text="Center | End"                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_cb"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/rb_eb"                     android:text="Center | Bottom"                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_cs"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/rb_eb"                     android:layout_marginLeft="5dp"                     android:layout_toRightOf="@+id/rb_cb"                     android:text="Center | Start"                     android:textColor="#FFFFFF" />                  <RadioButton                     android:id="@+id/rb_c"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_below="@+id/rb_eb"                     android:layout_marginLeft="5dp"                     android:layout_toRightOf="@+id/rb_cs"                     android:text="Center"                     android:textColor="#FFFFFF" />             </RelativeLayout>              <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:orientation="horizontal">                  <LinearLayout                     android:layout_width="0dp"                     android:layout_height="wrap_content"                     android:layout_weight="1"                     android:orientation="vertical"                     android:gravity="center_horizontal">                      <TextView                         android:id="@+id/tv_offsetx"                         android:layout_width="wrap_content"                         android:layout_height="wrap_content"                         android:text="GravityOffsetX : 1"                         android:textColor="#FFFFFF" />                      <SeekBar                         android:id="@+id/seekBar_offsetx"                         style="@style/Widget.AppCompat.SeekBar.Discrete"                         android:layout_width="match_parent"                         android:layout_height="wrap_content"                         android:layout_marginBottom="10dp"                         android:layout_marginTop="10dp"                         android:max="20"                         android:progress="1" />                  </LinearLayout>                  <LinearLayout                     android:layout_width="0dp"                     android:layout_height="wrap_content"                     android:layout_weight="1"                     android:orientation="vertical"                     android:gravity="center_horizontal">                      <TextView                         android:id="@+id/tv_offsety"                         android:layout_width="wrap_content"                         android:layout_height="wrap_content"                         android:text="GravityOffsetY : 1"                         android:textColor="#FFFFFF" />                     <SeekBar                         android:id="@+id/seekBar_offsety"                         style="@style/Widget.AppCompat.SeekBar.Discrete"                         android:layout_width="match_parent"                         android:layout_height="wrap_content"                         android:layout_marginBottom="10dp"                         android:layout_marginTop="10dp"                         android:max="20"                         android:progress="1" />                  </LinearLayout>             </LinearLayout>              <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:gravity="center_vertical"                 android:orientation="horizontal">                 <TextView                     android:id="@+id/tv_padding"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:text="BadgePadding : 5"                     android:textColor="#FFFFFF" />                  <SeekBar                     android:id="@+id/seekBar_padding"                     style="@style/Widget.AppCompat.SeekBar.Discrete"                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:layout_marginBottom="10dp"                     android:layout_marginTop="10dp"                     android:max="20"                     android:progress="5" />             </LinearLayout>             <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_marginBottom="10dp"                 android:layout_marginTop="10dp"                 android:gravity="center_vertical"                 android:orientation="horizontal">                  <TextView                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:text="BadgeColor : "                     android:textColor="#FFFFFF" />                  <ImageView                     android:id="@+id/iv_badgecolor"                     android:layout_width="30dp"                     android:layout_height="30dp"                     android:layout_marginLeft="5dp"                     android:background="#E84E40" />                  <TextView                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_marginLeft="30dp"                     android:text="ShowShadow : "                     android:textColor="#FFFFFF" />                  <Switch                     android:id="@+id/swicth_shadow"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:checked="true" />              </LinearLayout>             <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_marginBottom="10dp"                 android:gravity="center_vertical"                 android:orientation="horizontal">                  <TextView                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:text="TextColor : "                     android:textColor="#FFFFFF" />                  <ImageView                     android:id="@+id/iv_numbercolor"                     android:layout_width="30dp"                     android:layout_height="30dp"                     android:layout_marginLeft="5dp"                     android:background="#FFFFFF" />                  <LinearLayout                     android:layout_width="0dp"                     android:layout_weight="1"                     android:layout_height="wrap_content"                     android:gravity="center"                     android:orientation="vertical">                      <TextView                         android:id="@+id/tv_numbersize"                         android:layout_width="wrap_content"                         android:layout_height="wrap_content"                         android:text="TextSize : 11"                         android:textColor="#FFFFFF" />                      <SeekBar                         android:id="@+id/seekBar_numbersize"                         style="@style/Widget.AppCompat.SeekBar.Discrete"                         android:layout_width="match_parent"                         android:layout_height="wrap_content"                         android:max="30"                         android:progress="11" />                 </LinearLayout>             </LinearLayout>             <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_marginBottom="10dp"                 android:gravity="center_vertical"                 android:orientation="horizontal">                  <TextView                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:text="BadgeNumber : "                     android:textColor="#FFFFFF" />                  <EditText                     android:id="@+id/et_badgenumber"                     android:layout_width="0dp"                     android:layout_height="wrap_content"                     android:layout_weight="1"                     android:inputType="numberSigned"                     android:maxLength="7"                     android:maxLines="1"                     android:paddingLeft="10dp"                     android:paddingRight="10dp"                     android:text="5"                     android:textColor="#FFFFFF" />                  <TextView                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:text="ExactMode : "                     android:textColor="#FFFFFF" />                  <Switch                     android:id="@+id/swicth_exact"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_marginLeft="10dp"                     android:checked="false" />             </LinearLayout>              <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_marginBottom="10dp"                 android:gravity="center_vertical"                 android:orientation="horizontal">                  <TextView                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:text="Text : "                     android:textColor="#FFFFFF" />                  <EditText                     android:id="@+id/et_badgetext"                     android:layout_width="0dp"                     android:layout_height="wrap_content"                     android:layout_weight="1"                     android:maxLines="1"                     android:paddingLeft="10dp"                     android:paddingRight="10dp"                     android:textColor="#FFFFFF" />               </LinearLayout>              <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_marginBottom="10dp"                 android:layout_marginTop="10dp"                 android:gravity="center_vertical"                 android:orientation="horizontal">                  <TextView                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:text="Draggable : "                     android:textColor="#FFFFFF" />                  <Switch                     android:id="@+id/swicth_draggable"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_marginLeft="10dp" />                  <TextView                     android:id="@+id/tv_dragstate"                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_marginLeft="50dp"                     android:text=""                     android:textColor="#FFFFFF"                     android:textSize="18sp" />             </LinearLayout>              <Button                 android:id="@+id/btn_animation"                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:text="animation" />         </LinearLayout>     </ScrollView> </LinearLayout> 
<resources>     <!-- Default screen margins, per the Android Design guidelines. -->     <dimen name="activity_horizontal_margin">16dp</dimen>     <dimen name="activity_vertical_margin">16dp</dimen> </resources> 
<resources>     <string name="app_name">My Application</string>     <string name="textview">TextView</string>     <string name="button">Button</string> </resources> 
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="https://schemas.android.com/apk/res/android">     <solid android:color="#ff03a9f4" />     <corners android:radius="2dp" /> </shape> 
import android.graphics.PointF; import android.graphics.drawable.Drawable; import android.view.View;  /**  * 接口  */  public interface Badge {      Badge setBadgeNumber(int badgeNum);      int getBadgeNumber();      Badge setBadgeText(String badgeText);      String getBadgeText();      Badge setExactMode(boolean isExact);      boolean isExactMode();      Badge setShowShadow(boolean showShadow);      boolean isShowShadow();      Badge setBadgeBackgroundColor(int color);      Badge stroke(int color, float width, boolean isDpValue);      int getBadgeBackgroundColor();      Badge setBadgeBackground(Drawable drawable);      Badge setBadgeBackground(Drawable drawable, boolean clip);      Drawable getBadgeBackground();      Badge setBadgeTextColor(int color);      int getBadgeTextColor();      Badge setBadgeTextSize(float size, boolean isSpValue);      float getBadgeTextSize(boolean isSpValue);      Badge setBadgePadding(float padding, boolean isDpValue);      float getBadgePadding(boolean isDpValue);      boolean isDraggable();      Badge setBadgeGravity(int gravity);      int getBadgeGravity();      Badge setGravityOffset(float offset, boolean isDpValue);      Badge setGravityOffset(float offsetX, float offsetY, boolean isDpValue);      float getGravityOffsetX(boolean isDpValue);      float getGravityOffsetY(boolean isDpValue);      Badge setOnDragStateChangedListener(OnDragStateChangedListener l);      PointF getDragCenter();      Badge bindTarget(View view);      View getTargetView();      void hide(boolean animate);      interface OnDragStateChangedListener {         int STATE_START = 1;         int STATE_DRAGGING = 2;         int STATE_DRAGGING_OUT_OF_RANGE = 3;         int STATE_CANCELED = 4;         int STATE_SUCCEED = 5;          void onDragStateChanged(int dragState, Badge badge, View targetView);     } }  
import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.util.Log;  import java.lang.ref.WeakReference; import java.util.Random;  import static android.content.ContentValues.TAG;  /**  * 自定义动画  * Animation :https://github.com/tyrantgit/ExplosionField  */  public class BadgeAnimator extends ValueAnimator {     private BitmapFragment[][] mFragments;     private WeakReference<QBadgeView> mWeakBadge;      public BadgeAnimator(Bitmap badgeBitmap, PointF center, QBadgeView badge) {         mWeakBadge = new WeakReference<>(badge);         setFloatValues(0f, 1f);         setDuration(500);         mFragments = getFragments(badgeBitmap, center);         addUpdateListener(new AnimatorUpdateListener() {             @Override             public void onAnimationUpdate(ValueAnimator animation) {                 QBadgeView badgeView = mWeakBadge.get();                 if (badgeView == null || !badgeView.isShown()) {                     cancel();                 } else {                     badgeView.invalidate();                 }             }         });         addListener(new AnimatorListenerAdapter() {             @Override             public void onAnimationEnd(Animator animation) {                 QBadgeView badgeView = mWeakBadge.get();                 if (badgeView != null) {                     badgeView.reset();                 }             }         });     }      public void draw(Canvas canvas) {         for (int i = 0; i < mFragments.length; i++) {             for (int j = 0; j < mFragments[i].length; j++) {                 BitmapFragment bf = mFragments[i][j];                 float value = Float.parseFloat(getAnimatedValue().toString());                 bf.updata(value, canvas);             }         }     }       private BitmapFragment[][] getFragments(Bitmap badgeBitmap, PointF center) {         int width = badgeBitmap.getWidth();         int height = badgeBitmap.getHeight();         float fragmentSize = Math.min(width, height) / 6f;         float startX = center.x - badgeBitmap.getWidth() / 2f;         float startY = center.y - badgeBitmap.getHeight() / 2f;         BitmapFragment[][] fragments = new BitmapFragment[(int) (height / fragmentSize)][(int) (width / fragmentSize)];         for (int i = 0; i < fragments.length; i++) {             for (int j = 0; j < fragments[i].length; j++) {                 BitmapFragment bf = new BitmapFragment();                 bf.color = badgeBitmap.getPixel((int) (j * fragmentSize), (int) (i * fragmentSize));                 bf.x = startX + j * fragmentSize;                 bf.y = startY + i * fragmentSize;                 bf.size = fragmentSize;                 bf.maxSize = Math.max(width, height);                 fragments[i][j] = bf;             }         }         badgeBitmap.recycle();         return fragments;     }      private class BitmapFragment {         Random random;         float x;         float y;         float size;         int color;         int maxSize;         Paint paint;          public BitmapFragment() {             paint = new Paint();             paint.setAntiAlias(true);             paint.setStyle(Paint.Style.FILL);             random = new Random();         }          public void updata(float value, Canvas canvas) {             paint.setColor(color);             x = x + 0.1f * random.nextInt(maxSize) * (random.nextFloat() - 0.5f);             y = y + 0.1f * random.nextInt(maxSize) * (random.nextFloat() - 0.5f);             canvas.drawCircle(x, y, size - value * size, paint);         }     } }  
 import android.content.Context;  /**  * dp px转换工具  */  public class DisplayUtil {     public static int dp2px(Context context, float dp) {         final float scale = context.getResources().getDisplayMetrics().density;         return (int) (dp * scale + 0.5f);     }      public static int px2dp(Context context, float pxValue) {         final float scale = context.getResources().getDisplayMetrics().density;         return (int) (pxValue / scale + 0.5f);     } }  
import android.graphics.PointF;  import java.util.List;  /**  * Created by chqiu on 2017/3/20.  */  public class MathUtil {     public static final double CIRCLE_RADIAN = 2 * Math.PI;      public static double getTanRadian(double atan, int quadrant) {         if (atan < 0) {             atan += CIRCLE_RADIAN / 4;         }         atan += CIRCLE_RADIAN / 4 * (quadrant - 1);         return atan;     }      public static double radianToAngle(double radian) {         return 360 * (radian / CIRCLE_RADIAN);     }      public static int getQuadrant(PointF p, PointF center) {         if (p.x > center.x) {             if (p.y > center.y) {                 return 4;             } else if (p.y < center.y) {                 return 1;             }         } else if (p.x < center.x) {             if (p.y > center.y) {                 return 3;             } else if (p.y < center.y) {                 return 2;             }         }         return -1;     }      public static float getPointDistance(PointF p1, PointF p2) {         return (float) Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));     }      /**      * this formula is designed by mabeijianxi      * website : https://blog.csdn.net/mabeijianxi/article/details/50560361      *      * @param circleCenter The circle center point.      * @param radius       The circle radius.      * @param slopeLine    The slope of line which cross the pMiddle.      */     public static void getInnertangentPoints(PointF circleCenter, float radius, Double slopeLine, List<PointF> points) {         float radian, xOffset, yOffset;         if (slopeLine != null) {             radian = (float) Math.atan(slopeLine);             xOffset = (float) (Math.cos(radian) * radius);             yOffset = (float) (Math.sin(radian) * radius);         } else {             xOffset = radius;             yOffset = 0;         }         points.add(new PointF(circleCenter.x + xOffset, circleCenter.y + yOffset));         points.add(new PointF(circleCenter.x - xOffset, circleCenter.y - yOffset));     } }  
import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Parcelable; import android.text.TextPaint; import android.text.TextUtils; import android.util.AttributeSet; import android.util.SparseArray; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.FrameLayout; import android.widget.RelativeLayout;  import java.util.ArrayList; import java.util.List;  /**  * 自定义QQ消息数量工具类  */  public class QBadgeView extends View implements Badge {     protected int mColorBackground;     protected int mColorBackgroundBorder;     protected int mColorBadgeText;     protected Drawable mDrawableBackground;     protected Bitmap mBitmapClip;     protected boolean mDrawableBackgroundClip;     protected float mBackgroundBorderWidth;     protected float mBadgeTextSize;     protected float mBadgePadding;     protected int mBadgeNumber;     protected String mBadgeText;     protected boolean mDraggable;     protected boolean mDragging;     protected boolean mExact;     protected boolean mShowShadow;     protected int mBadgeGravity;     protected float mGravityOffsetX;     protected float mGravityOffsetY;      protected float mDefalutRadius;     protected float mFinalDragDistance;     protected int mDragQuadrant;     protected boolean mDragOutOfRange;      protected RectF mBadgeTextRect;     protected RectF mBadgeBackgroundRect;     protected Path mDragPath;      protected Paint.FontMetrics mBadgeTextFontMetrics;      protected PointF mBadgeCenter;     protected PointF mDragCenter;     protected PointF mRowBadgeCenter;     protected PointF mControlPoint;      protected List<PointF> mInnertangentPoints;      protected View mTargetView;      protected int mWidth;     protected int mHeight;      protected TextPaint mBadgeTextPaint;     protected Paint mBadgeBackgroundPaint;     protected Paint mBadgeBackgroundBorderPaint;      protected BadgeAnimator mAnimator;      protected OnDragStateChangedListener mDragStateChangedListener;      protected ViewGroup mActivityRoot;      public QBadgeView(Context context) {         this(context, null);     }      private QBadgeView(Context context, AttributeSet attrs) {         this(context, attrs, 0);     }      private QBadgeView(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);         init();     }      private void init() {         setLayerType(View.LAYER_TYPE_SOFTWARE, null);         mBadgeTextRect = new RectF();         mBadgeBackgroundRect = new RectF();         mDragPath = new Path();         mBadgeCenter = new PointF();         mDragCenter = new PointF();         mRowBadgeCenter = new PointF();         mControlPoint = new PointF();         mInnertangentPoints = new ArrayList<>();         mBadgeTextPaint = new TextPaint();         mBadgeTextPaint.setAntiAlias(true);         mBadgeTextPaint.setSubpixelText(true);         mBadgeTextPaint.setFakeBoldText(true);         mBadgeTextPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));         mBadgeBackgroundPaint = new Paint();         mBadgeBackgroundPaint.setAntiAlias(true);         mBadgeBackgroundPaint.setStyle(Paint.Style.FILL);         mBadgeBackgroundBorderPaint = new Paint();         mBadgeBackgroundBorderPaint.setAntiAlias(true);         mBadgeBackgroundBorderPaint.setStyle(Paint.Style.STROKE);         mColorBackground = 0xFFE84E40;         mColorBadgeText = 0xFFFFFFFF;         mBadgeTextSize = DisplayUtil.dp2px(getContext(), 11);         mBadgePadding = DisplayUtil.dp2px(getContext(), 5);         mBadgeNumber = 0;         mBadgeGravity = Gravity.END | Gravity.TOP;         mGravityOffsetX = DisplayUtil.dp2px(getContext(), 1);         mGravityOffsetY = DisplayUtil.dp2px(getContext(), 1);         mFinalDragDistance = DisplayUtil.dp2px(getContext(), 90);         mShowShadow = true;         mDrawableBackgroundClip = false;         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {             setTranslationZ(1000);         }     }      @Override     public Badge bindTarget(final View targetView) {         if (targetView == null) {             throw new IllegalStateException("targetView can not be null");         }         if (getParent() != null) {             ((ViewGroup) getParent()).removeView(this);         }         ViewParent targetParent = targetView.getParent();         if (targetParent != null && targetParent instanceof ViewGroup) {             mTargetView = targetView;             if (targetParent instanceof BadgeContainer) {                 ((BadgeContainer) targetParent).addView(this);             } else {                 ViewGroup targetContainer = (ViewGroup) targetParent;                 int index = targetContainer.indexOfChild(targetView);                 ViewGroup.LayoutParams targetParams = targetView.getLayoutParams();                 targetContainer.removeView(targetView);                 final BadgeContainer badgeContainer = new BadgeContainer(getContext());                 if(targetContainer instanceof RelativeLayout){                     badgeContainer.setId(targetView.getId());                 }                 targetContainer.addView(badgeContainer, index, targetParams);                 badgeContainer.addView(targetView);                 badgeContainer.addView(this);             }         } else {             throw new IllegalStateException("targetView must have a parent");         }         return this;     }      @Override     public View getTargetView() {         return mTargetView;     }      @Override     protected void onAttachedToWindow() {         super.onAttachedToWindow();         if (mActivityRoot == null) findViewRoot(mTargetView);     }      private void findViewRoot(View view) {         mActivityRoot = (ViewGroup) view.getRootView();         if (mActivityRoot == null) {             findActivityRoot(view);         }     }      private void findActivityRoot(View view) {         if (view.getParent() != null && view.getParent() instanceof View) {             findActivityRoot((View) view.getParent());         } else if (view instanceof ViewGroup) {             mActivityRoot = (ViewGroup) view;         }     }      @Override     public boolean onTouchEvent(MotionEvent event) {         switch (event.getActionMasked()) {             case MotionEvent.ACTION_DOWN:             case MotionEvent.ACTION_POINTER_DOWN:                 float x = event.getX();                 float y = event.getY();                 if (mDraggable && event.getPointerId(event.getActionIndex()) == 0                         && (x > mBadgeBackgroundRect.left && x < mBadgeBackgroundRect.right &&                         y > mBadgeBackgroundRect.top && y < mBadgeBackgroundRect.bottom)                         && mBadgeText != null) {                     initRowBadgeCenter();                     mDragging = true;                     updataListener(OnDragStateChangedListener.STATE_START);                     mDefalutRadius = DisplayUtil.dp2px(getContext(), 7);                     getParent().requestDisallowInterceptTouchEvent(true);                     screenFromWindow(true);                     mDragCenter.x = event.getRawX();                     mDragCenter.y = event.getRawY();                 }                 break;             case MotionEvent.ACTION_MOVE:                 if (mDragging) {                     mDragCenter.x = event.getRawX();                     mDragCenter.y = event.getRawY();                     invalidate();                 }                 break;             case MotionEvent.ACTION_UP:             case MotionEvent.ACTION_POINTER_UP:             case MotionEvent.ACTION_CANCEL:                 if (event.getPointerId(event.getActionIndex()) == 0 && mDragging) {                     mDragging = false;                     onPointerUp();                 }                 break;         }         return mDragging || super.onTouchEvent(event);     }      private void onPointerUp() {         if (mDragOutOfRange) {             animateHide(mDragCenter);             updataListener(OnDragStateChangedListener.STATE_SUCCEED);         } else {             reset();             updataListener(OnDragStateChangedListener.STATE_CANCELED);         }     }      protected Bitmap createBadgeBitmap() {         Bitmap bitmap = Bitmap.createBitmap((int) mBadgeBackgroundRect.width() + DisplayUtil.dp2px(getContext(), 3),                 (int) mBadgeBackgroundRect.height() + DisplayUtil.dp2px(getContext(), 3), Bitmap.Config.ARGB_8888);         Canvas canvas = new Canvas(bitmap);         drawBadge(canvas, new PointF(canvas.getWidth() / 2f, canvas.getHeight() / 2f), getBadgeCircleRadius());         return bitmap;     }      protected void screenFromWindow(boolean screen) {         if (getParent() != null) {             ((ViewGroup) getParent()).removeView(this);         }         if (screen) {             mActivityRoot.addView(this, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,                     FrameLayout.LayoutParams.MATCH_PARENT));         } else {             bindTarget(mTargetView);         }     }      private void showShadowImpl(boolean showShadow) {         int x = DisplayUtil.dp2px(getContext(), 1);         int y = DisplayUtil.dp2px(getContext(), 1.5f);         switch (mDragQuadrant) {             case 1:                 x = DisplayUtil.dp2px(getContext(), 1);                 y = DisplayUtil.dp2px(getContext(), -1.5f);                 break;             case 2:                 x = DisplayUtil.dp2px(getContext(), -1);                 y = DisplayUtil.dp2px(getContext(), -1.5f);                 break;             case 3:                 x = DisplayUtil.dp2px(getContext(), -1);                 y = DisplayUtil.dp2px(getContext(), 1.5f);                 break;             case 4:                 x = DisplayUtil.dp2px(getContext(), 1);                 y = DisplayUtil.dp2px(getContext(), 1.5f);                 break;         }         mBadgeBackgroundPaint.setShadowLayer(showShadow ? DisplayUtil.dp2px(getContext(), 2f)                 : 0, x, y, 0x33000000);     }      @Override     protected void onSizeChanged(int w, int h, int oldw, int oldh) {         super.onSizeChanged(w, h, oldw, oldh);         mWidth = w;         mHeight = h;     }      @Override     protected void onDraw(Canvas canvas) {         if (mAnimator != null && mAnimator.isRunning()) {             mAnimator.draw(canvas);             return;         }         if (mBadgeText != null) {             initPaints();             float badgeRadius = getBadgeCircleRadius();             float startCircleRadius = mDefalutRadius * (1 - MathUtil.getPointDistance                     (mRowBadgeCenter, mDragCenter) / mFinalDragDistance);             if (mDraggable && mDragging) {                 mDragQuadrant = MathUtil.getQuadrant(mDragCenter, mRowBadgeCenter);                 showShadowImpl(mShowShadow);                 if (mDragOutOfRange = startCircleRadius < DisplayUtil.dp2px(getContext(), 1.5f)) {                     updataListener(OnDragStateChangedListener.STATE_DRAGGING_OUT_OF_RANGE);                     drawBadge(canvas, mDragCenter, badgeRadius);                 } else {                     updataListener(OnDragStateChangedListener.STATE_DRAGGING);                     drawDragging(canvas, startCircleRadius, badgeRadius);                     drawBadge(canvas, mDragCenter, badgeRadius);                 }             } else {                 findBadgeCenter();                 drawBadge(canvas, mBadgeCenter, badgeRadius);             }         }     }      private void initPaints() {         showShadowImpl(mShowShadow);         mBadgeBackgroundPaint.setColor(mColorBackground);         mBadgeBackgroundBorderPaint.setColor(mColorBackgroundBorder);         mBadgeBackgroundBorderPaint.setStrokeWidth(mBackgroundBorderWidth);         mBadgeTextPaint.setColor(mColorBadgeText);         mBadgeTextPaint.setTextAlign(Paint.Align.CENTER);     }      private void drawDragging(Canvas canvas, float startRadius, float badgeRadius) {         float dy = mDragCenter.y - mRowBadgeCenter.y;         float dx = mDragCenter.x - mRowBadgeCenter.x;         mInnertangentPoints.clear();         if (dx != 0) {             double k1 = dy / dx;             double k2 = -1 / k1;             MathUtil.getInnertangentPoints(mDragCenter, badgeRadius, k2, mInnertangentPoints);             MathUtil.getInnertangentPoints(mRowBadgeCenter, startRadius, k2, mInnertangentPoints);         } else {             MathUtil.getInnertangentPoints(mDragCenter, badgeRadius, 0d, mInnertangentPoints);             MathUtil.getInnertangentPoints(mRowBadgeCenter, startRadius, 0d, mInnertangentPoints);         }         mDragPath.reset();         mDragPath.addCircle(mRowBadgeCenter.x, mRowBadgeCenter.y, startRadius,                 mDragQuadrant == 1 || mDragQuadrant == 2 ? Path.Direction.CCW : Path.Direction.CW);         mControlPoint.x = (mRowBadgeCenter.x + mDragCenter.x) / 2.0f;         mControlPoint.y = (mRowBadgeCenter.y + mDragCenter.y) / 2.0f;         mDragPath.moveTo(mInnertangentPoints.get(2).x, mInnertangentPoints.get(2).y);         mDragPath.quadTo(mControlPoint.x, mControlPoint.y, mInnertangentPoints.get(0).x, mInnertangentPoints.get(0).y);         mDragPath.lineTo(mInnertangentPoints.get(1).x, mInnertangentPoints.get(1).y);         mDragPath.quadTo(mControlPoint.x, mControlPoint.y, mInnertangentPoints.get(3).x, mInnertangentPoints.get(3).y);         mDragPath.lineTo(mInnertangentPoints.get(2).x, mInnertangentPoints.get(2).y);         mDragPath.close();         canvas.drawPath(mDragPath, mBadgeBackgroundPaint);          //draw dragging border         if (mColorBackgroundBorder != 0 && mBackgroundBorderWidth > 0) {             mDragPath.reset();             mDragPath.moveTo(mInnertangentPoints.get(2).x, mInnertangentPoints.get(2).y);             mDragPath.quadTo(mControlPoint.x, mControlPoint.y, mInnertangentPoints.get(0).x, mInnertangentPoints.get(0).y);             mDragPath.moveTo(mInnertangentPoints.get(1).x, mInnertangentPoints.get(1).y);             mDragPath.quadTo(mControlPoint.x, mControlPoint.y, mInnertangentPoints.get(3).x, mInnertangentPoints.get(3).y);             float startY;             float startX;             if (mDragQuadrant == 1 || mDragQuadrant == 2) {                 startX = mInnertangentPoints.get(2).x - mRowBadgeCenter.x;                 startY = mRowBadgeCenter.y - mInnertangentPoints.get(2).y;             } else {                 startX = mInnertangentPoints.get(3).x - mRowBadgeCenter.x;                 startY = mRowBadgeCenter.y - mInnertangentPoints.get(3).y;             }             float startAngle = 360 - (float) MathUtil.radianToAngle(MathUtil.getTanRadian(Math.atan(startY / startX),                     mDragQuadrant - 1 == 0 ? 4 : mDragQuadrant - 1));             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {                 mDragPath.addArc(mRowBadgeCenter.x - startRadius, mRowBadgeCenter.y - startRadius,                         mRowBadgeCenter.x + startRadius, mRowBadgeCenter.y + startRadius, startAngle,                         180);             } else {                 mDragPath.addArc(new RectF(mRowBadgeCenter.x - startRadius, mRowBadgeCenter.y - startRadius,                         mRowBadgeCenter.x + startRadius, mRowBadgeCenter.y + startRadius), startAngle, 180);             }             canvas.drawPath(mDragPath, mBadgeBackgroundBorderPaint);         }     }      private void drawBadge(Canvas canvas, PointF center, float radius) {         if (center.x == -1000 && center.y == -1000) {             return;         }         if (mBadgeText.isEmpty() || mBadgeText.length() == 1) {             mBadgeBackgroundRect.left = center.x - (int) radius;             mBadgeBackgroundRect.top = center.y - (int) radius;             mBadgeBackgroundRect.right = center.x + (int) radius;             mBadgeBackgroundRect.bottom = center.y + (int) radius;             if (mDrawableBackground != null) {                 drawBadgeBackground(canvas);             } else {                 canvas.drawCircle(center.x, center.y, radius, mBadgeBackgroundPaint);                 if (mColorBackgroundBorder != 0 && mBackgroundBorderWidth > 0) {                     canvas.drawCircle(center.x, center.y, radius, mBadgeBackgroundBorderPaint);                 }             }         } else {             mBadgeBackgroundRect.left = center.x - (mBadgeTextRect.width() / 2f + mBadgePadding);             mBadgeBackgroundRect.top = center.y - (mBadgeTextRect.height() / 2f + mBadgePadding * 0.5f);             mBadgeBackgroundRect.right = center.x + (mBadgeTextRect.width() / 2f + mBadgePadding);             mBadgeBackgroundRect.bottom = center.y + (mBadgeTextRect.height() / 2f + mBadgePadding * 0.5f);             radius = mBadgeBackgroundRect.height() / 2f;             if (mDrawableBackground != null) {                 drawBadgeBackground(canvas);             } else {                 canvas.drawRoundRect(mBadgeBackgroundRect, radius, radius, mBadgeBackgroundPaint);                 if (mColorBackgroundBorder != 0 && mBackgroundBorderWidth > 0) {                     canvas.drawRoundRect(mBadgeBackgroundRect, radius, radius, mBadgeBackgroundBorderPaint);                 }             }         }         if (!mBadgeText.isEmpty()) {             canvas.drawText(mBadgeText, center.x,                     (mBadgeBackgroundRect.bottom + mBadgeBackgroundRect.top                             - mBadgeTextFontMetrics.bottom - mBadgeTextFontMetrics.top) / 2f,                     mBadgeTextPaint);         }     }      private void drawBadgeBackground(Canvas canvas) {         mBadgeBackgroundPaint.setShadowLayer(0, 0, 0, 0);         int left = (int) mBadgeBackgroundRect.left;         int top = (int) mBadgeBackgroundRect.top;         int right = (int) mBadgeBackgroundRect.right;         int bottom = (int) mBadgeBackgroundRect.bottom;         if (mDrawableBackgroundClip) {             right = left + mBitmapClip.getWidth();             bottom = top + mBitmapClip.getHeight();             canvas.saveLayer(left, top, right, bottom, null, Canvas.ALL_SAVE_FLAG);         }         mDrawableBackground.setBounds(left, top, right, bottom);         mDrawableBackground.draw(canvas);         if (mDrawableBackgroundClip) {             mBadgeBackgroundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));             canvas.drawBitmap(mBitmapClip, left, top, mBadgeBackgroundPaint);             canvas.restore();             mBadgeBackgroundPaint.setXfermode(null);             if (mBadgeText.isEmpty() || mBadgeText.length() == 1) {                 canvas.drawCircle(mBadgeBackgroundRect.centerX(), mBadgeBackgroundRect.centerY(),                         mBadgeBackgroundRect.width() / 2f, mBadgeBackgroundBorderPaint);             } else {                 canvas.drawRoundRect(mBadgeBackgroundRect,                         mBadgeBackgroundRect.height() / 2, mBadgeBackgroundRect.height() / 2,                         mBadgeBackgroundBorderPaint);             }         } else {             canvas.drawRect(mBadgeBackgroundRect, mBadgeBackgroundBorderPaint);         }     }      private void createClipLayer() {         if (mBadgeText == null) {             return;         }         if (!mDrawableBackgroundClip) {             return;         }         if (mBitmapClip != null && !mBitmapClip.isRecycled()) {             mBitmapClip.recycle();         }         float radius = getBadgeCircleRadius();         if (mBadgeText.isEmpty() || mBadgeText.length() == 1) {             mBitmapClip = Bitmap.createBitmap((int) radius * 2, (int) radius * 2,                     Bitmap.Config.ARGB_4444);             Canvas srcCanvas = new Canvas(mBitmapClip);             srcCanvas.drawCircle(srcCanvas.getWidth() / 2f, srcCanvas.getHeight() / 2f,                     srcCanvas.getWidth() / 2f, mBadgeBackgroundPaint);         } else {             mBitmapClip = Bitmap.createBitmap((int) (mBadgeTextRect.width() + mBadgePadding * 2),                     (int) (mBadgeTextRect.height() + mBadgePadding), Bitmap.Config.ARGB_4444);             Canvas srcCanvas = new Canvas(mBitmapClip);             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {                 srcCanvas.drawRoundRect(0, 0, srcCanvas.getWidth(), srcCanvas.getHeight(), srcCanvas.getHeight() / 2f,                         srcCanvas.getHeight() / 2f, mBadgeBackgroundPaint);             } else {                 srcCanvas.drawRoundRect(new RectF(0, 0, srcCanvas.getWidth(), srcCanvas.getHeight()),                         srcCanvas.getHeight() / 2f, srcCanvas.getHeight() / 2f, mBadgeBackgroundPaint);             }         }     }      private float getBadgeCircleRadius() {         if (mBadgeText.isEmpty()) {             return mBadgePadding;         } else if (mBadgeText.length() == 1) {             return mBadgeTextRect.height() > mBadgeTextRect.width() ?                     mBadgeTextRect.height() / 2f + mBadgePadding * 0.5f :                     mBadgeTextRect.width() / 2f + mBadgePadding * 0.5f;         } else {             return mBadgeBackgroundRect.height() / 2f;         }     }      private void findBadgeCenter() {         float rectWidth = mBadgeTextRect.height() > mBadgeTextRect.width() ?                 mBadgeTextRect.height() : mBadgeTextRect.width();         switch (mBadgeGravity) {             case Gravity.START | Gravity.TOP:                 mBadgeCenter.x = mGravityOffsetX + mBadgePadding + rectWidth / 2f;                 mBadgeCenter.y = mGravityOffsetY + mBadgePadding + mBadgeTextRect.height() / 2f;                 break;             case Gravity.START | Gravity.BOTTOM:                 mBadgeCenter.x = mGravityOffsetX + mBadgePadding + rectWidth / 2f;                 mBadgeCenter.y = mHeight - (mGravityOffsetY + mBadgePadding + mBadgeTextRect.height() / 2f);                 break;             case Gravity.END | Gravity.TOP:                 mBadgeCenter.x = mWidth - (mGravityOffsetX + mBadgePadding + rectWidth / 2f);                 mBadgeCenter.y = mGravityOffsetY + mBadgePadding + mBadgeTextRect.height() / 2f;                 break;             case Gravity.END | Gravity.BOTTOM:                 mBadgeCenter.x = mWidth - (mGravityOffsetX + mBadgePadding + rectWidth / 2f);                 mBadgeCenter.y = mHeight - (mGravityOffsetY + mBadgePadding + mBadgeTextRect.height() / 2f);                 break;             case Gravity.CENTER:                 mBadgeCenter.x = mWidth / 2f;                 mBadgeCenter.y = mHeight / 2f;                 break;             case Gravity.CENTER | Gravity.TOP:                 mBadgeCenter.x = mWidth / 2f;                 mBadgeCenter.y = mGravityOffsetY + mBadgePadding + mBadgeTextRect.height() / 2f;                 break;             case Gravity.CENTER | Gravity.BOTTOM:                 mBadgeCenter.x = mWidth / 2f;                 mBadgeCenter.y = mHeight - (mGravityOffsetY + mBadgePadding + mBadgeTextRect.height() / 2f);                 break;             case Gravity.CENTER | Gravity.START:                 mBadgeCenter.x = mGravityOffsetX + mBadgePadding + rectWidth / 2f;                 mBadgeCenter.y = mHeight / 2f;                 break;             case Gravity.CENTER | Gravity.END:                 mBadgeCenter.x = mWidth - (mGravityOffsetX + mBadgePadding + rectWidth / 2f);                 mBadgeCenter.y = mHeight / 2f;                 break;         }         initRowBadgeCenter();     }      private void measureText() {         mBadgeTextRect.left = 0;         mBadgeTextRect.top = 0;         if (TextUtils.isEmpty(mBadgeText)) {             mBadgeTextRect.right = 0;             mBadgeTextRect.bottom = 0;         } else {             mBadgeTextPaint.setTextSize(mBadgeTextSize);             mBadgeTextRect.right = mBadgeTextPaint.measureText(mBadgeText);             mBadgeTextFontMetrics = mBadgeTextPaint.getFontMetrics();             mBadgeTextRect.bottom = mBadgeTextFontMetrics.descent - mBadgeTextFontMetrics.ascent;         }         createClipLayer();     }      private void initRowBadgeCenter() {         int[] screenPoint = new int[2];         getLocationOnScreen(screenPoint);         mRowBadgeCenter.x = mBadgeCenter.x + screenPoint[0];         mRowBadgeCenter.y = mBadgeCenter.y + screenPoint[1];     }      protected void animateHide(PointF center) {         if (mBadgeText == null) {             return;         }         if (mAnimator == null || !mAnimator.isRunning()) {             screenFromWindow(true);             mAnimator = new BadgeAnimator(createBadgeBitmap(), center, this);             mAnimator.start();             setBadgeNumber(0);         }     }      public void reset() {         mDragCenter.x = -1000;         mDragCenter.y = -1000;         mDragQuadrant = 4;         screenFromWindow(false);         getParent().requestDisallowInterceptTouchEvent(false);         invalidate();     }      @Override     public void hide(boolean animate) {         if (animate && mActivityRoot != null) {             initRowBadgeCenter();             animateHide(mRowBadgeCenter);         } else {             setBadgeNumber(0);         }     }      /**      * @param badgeNumber equal to zero badge will be hidden, less than zero show dot      */     @Override     public Badge setBadgeNumber(int badgeNumber) {         mBadgeNumber = badgeNumber;         if (mBadgeNumber < 0) {             mBadgeText = "";         } else if (mBadgeNumber > 99) {             mBadgeText = mExact ? String.valueOf(mBadgeNumber) : "99+";         } else if (mBadgeNumber > 0 && mBadgeNumber <= 99) {             mBadgeText = String.valueOf(mBadgeNumber);         } else if (mBadgeNumber == 0) {             mBadgeText = null;         }         measureText();         invalidate();         return this;     }      @Override     public int getBadgeNumber() {         return mBadgeNumber;     }      @Override     public Badge setBadgeText(String badgeText) {         mBadgeText = badgeText;         mBadgeNumber = 1;         measureText();         invalidate();         return this;     }      @Override     public String getBadgeText() {         return mBadgeText;     }      @Override     public Badge setExactMode(boolean isExact) {         mExact = isExact;         if (mBadgeNumber > 99) {             setBadgeNumber(mBadgeNumber);         }         return this;     }      @Override     public boolean isExactMode() {         return mExact;     }      @Override     public Badge setShowShadow(boolean showShadow) {         mShowShadow = showShadow;         invalidate();         return this;     }      @Override     public boolean isShowShadow() {         return mShowShadow;     }      @Override     public Badge setBadgeBackgroundColor(int color) {         mColorBackground = color;         if (mColorBackground == Color.TRANSPARENT) {             mBadgeTextPaint.setXfermode(null);         } else {             mBadgeTextPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));         }         invalidate();         return this;     }      @Override     public Badge stroke(int color, float width, boolean isDpValue) {         mColorBackgroundBorder = color;         mBackgroundBorderWidth = isDpValue ? DisplayUtil.dp2px(getContext(), width) : width;         invalidate();         return this;     }      @Override     public int getBadgeBackgroundColor() {         return mColorBackground;     }      @Override     public Badge setBadgeBackground(Drawable drawable) {         return setBadgeBackground(drawable, false);     }      @Override     public Badge setBadgeBackground(Drawable drawable, boolean clip) {         mDrawableBackgroundClip = clip;         mDrawableBackground = drawable;         createClipLayer();         invalidate();         return this;     }      @Override     public Drawable getBadgeBackground() {         return mDrawableBackground;     }      @Override     public Badge setBadgeTextColor(int color) {         mColorBadgeText = color;         invalidate();         return this;     }      @Override     public int getBadgeTextColor() {         return mColorBadgeText;     }      @Override     public Badge setBadgeTextSize(float size, boolean isSpValue) {         mBadgeTextSize = isSpValue ? DisplayUtil.dp2px(getContext(), size) : size;         measureText();         invalidate();         return this;     }      @Override     public float getBadgeTextSize(boolean isSpValue) {         return isSpValue ? DisplayUtil.px2dp(getContext(), mBadgeTextSize) : mBadgeTextSize;     }      @Override     public Badge setBadgePadding(float padding, boolean isDpValue) {         mBadgePadding = isDpValue ? DisplayUtil.dp2px(getContext(), padding) : padding;         createClipLayer();         invalidate();         return this;     }      @Override     public float getBadgePadding(boolean isDpValue) {         return isDpValue ? DisplayUtil.px2dp(getContext(), mBadgePadding) : mBadgePadding;     }      @Override     public boolean isDraggable() {         return mDraggable;     }      /**      * @param gravity only support Gravity.START | Gravity.TOP , Gravity.END | Gravity.TOP ,      *                Gravity.START | Gravity.BOTTOM , Gravity.END | Gravity.BOTTOM ,      *                Gravity.CENTER , Gravity.CENTER | Gravity.TOP , Gravity.CENTER | Gravity.BOTTOM ,      *                Gravity.CENTER | Gravity.START , Gravity.CENTER | Gravity.END      */     @Override     public Badge setBadgeGravity(int gravity) {         if (gravity == (Gravity.START | Gravity.TOP) ||                 gravity == (Gravity.END | Gravity.TOP) ||                 gravity == (Gravity.START | Gravity.BOTTOM) ||                 gravity == (Gravity.END | Gravity.BOTTOM) ||                 gravity == (Gravity.CENTER) ||                 gravity == (Gravity.CENTER | Gravity.TOP) ||                 gravity == (Gravity.CENTER | Gravity.BOTTOM) ||                 gravity == (Gravity.CENTER | Gravity.START) ||                 gravity == (Gravity.CENTER | Gravity.END)) {             mBadgeGravity = gravity;             invalidate();         } else {             throw new IllegalStateException("only support Gravity.START | Gravity.TOP , Gravity.END | Gravity.TOP , " +                     "Gravity.START | Gravity.BOTTOM , Gravity.END | Gravity.BOTTOM , Gravity.CENTER" +                     " , Gravity.CENTER | Gravity.TOP , Gravity.CENTER | Gravity.BOTTOM ," +                     "Gravity.CENTER | Gravity.START , Gravity.CENTER | Gravity.END");         }         return this;     }      @Override     public int getBadgeGravity() {         return mBadgeGravity;     }      @Override     public Badge setGravityOffset(float offset, boolean isDpValue) {         return setGravityOffset(offset, offset, isDpValue);     }      @Override     public Badge setGravityOffset(float offsetX, float offsetY, boolean isDpValue) {         mGravityOffsetX = isDpValue ? DisplayUtil.dp2px(getContext(), offsetX) : offsetX;         mGravityOffsetY = isDpValue ? DisplayUtil.dp2px(getContext(), offsetY) : offsetY;         invalidate();         return this;     }      @Override     public float getGravityOffsetX(boolean isDpValue) {         return isDpValue ? DisplayUtil.px2dp(getContext(), mGravityOffsetX) : mGravityOffsetX;     }      @Override     public float getGravityOffsetY(boolean isDpValue) {         return isDpValue ? DisplayUtil.px2dp(getContext(), mGravityOffsetY) : mGravityOffsetY;     }       private void updataListener(int state) {         if (mDragStateChangedListener != null)             mDragStateChangedListener.onDragStateChanged(state, this, mTargetView);     }      @Override     public Badge setOnDragStateChangedListener(OnDragStateChangedListener l) {         mDraggable = l != null;         mDragStateChangedListener = l;         return this;     }      @Override     public PointF getDragCenter() {         if (mDraggable && mDragging) return mDragCenter;         return null;     }      private class BadgeContainer extends ViewGroup {          @Override         protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {             if(!(getParent() instanceof RelativeLayout)){                 super.dispatchRestoreInstanceState(container);             }         }          public BadgeContainer(Context context) {             super(context);         }          @Override         protected void onLayout(boolean changed, int l, int t, int r, int b) {             for (int i = 0; i < getChildCount(); i++) {                 View child = getChildAt(i);                 child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());             }         }          @Override         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {             View targetView = null, badgeView = null;             for (int i = 0; i < getChildCount(); i++) {                 View child = getChildAt(i);                 if (!(child instanceof QBadgeView)) {                     targetView = child;                 } else {                     badgeView = child;                 }             }             if (targetView == null) {                 super.onMeasure(widthMeasureSpec, heightMeasureSpec);             } else {                 targetView.measure(widthMeasureSpec, heightMeasureSpec);                 if (badgeView != null) {                     badgeView.measure(MeasureSpec.makeMeasureSpec(targetView.getMeasuredWidth(), MeasureSpec.EXACTLY),                             MeasureSpec.makeMeasureSpec(targetView.getMeasuredHeight(), MeasureSpec.EXACTLY));                 }                 setMeasuredDimension(targetView.getMeasuredWidth(), targetView.getMeasuredHeight());             }         }     } }  
import java.util.ArrayList; import java.util.List;  /**  * 模拟数据类  */  public class DataSupport {     private List<String> mDatas;      public DataSupport() {         mDatas = new ArrayList<>();         mDatas.add("(`・ω・´)ฅ铲屎官快来");         mDatas.add("ฅ(´-ω-`)ฅ好酥胡");         mDatas.add("~(=^・ω・^)ฅ☆ 澡桑嚎啊小婊贝");         mDatas.add("(=ฅರ﹏ರ)ฅ我要小鱼干");         mDatas.add("(ฅ‵皿′)ฅ︵┻┻ 为什么不跟我玩儿");         mDatas.add("ヽ(ฅ≧へ≦)ฅ饭不好吃");         mDatas.add("(╬ ̄皿 ̄)ฅ拒绝洗澡");         mDatas.add("ฅ(= ̄. ̄||)ฅ愚蠢的人类");         mDatas.add("☆*:.。. ฅ(≧▽≦)ฅ .。.:*☆ ");         mDatas.add("ヾ((๑˘ㅂ˘๑)ฅ^._.^ฅ我萌吗");         mDatas.add("༻ི(ؔᵒ̶̷ᵕؔᵒ̷̶)༄୭*ˈ 浪到飞起");         mDatas.add("*:ஐ٩(๑´ᵕ`)۶ஐ:* 透心凉心飞扬");         mDatas.add("˚₊*୧⃛(๑⃙⃘⁼̴̀꒳⁼̴́๑⃙⃘)୨⃛*₊˚⋆ 精神百倍");         mDatas.add("٩(ꇐ‿ꇐ)۶世界那么大我想去看看");         mDatas.add("๛꜀꒰ ˟⌂˟꜀ ꜆꒱꜆ 起来,不愿做作业的人们");         mDatas.add("˚‧·(´ฅ・ェ・ฅ‘)‧º.喵,救命啊,人家怕水");         mDatas.add("(^,,ԾェԾ,,^)这款裙子是为本宝宝定制的吗");         mDatas.add("ლ(ಠェಠ)و美图软件用的好,老公才好找");         mDatas.add("(҂`・ェ・´) <,︻╦̵̵̿╤─ ҉ - -- 让你秀恩爱!");         mDatas.add("为你加油!!!!!!n" +                 " ☆  * .   ☆n" +                 "  . ∧_∧ ∩ * ☆n" +                 "*  ☆ ( ・∀・)/ .n" +                 " .  ⊂   ノ* ☆n" +                 "☆ * (つ ノ  .☆n" +                 "   (ノ");         mDatas.add("老n" +                 " 板n" +                 "  说n" +                 "   今n" +                 "    天n" +                 "     放n" +                 "      假n" +                 "        !n" +                 " ヽ\  //n" +                 "    ∧∧ 。n" +                 "  ゚ (゚∀゚)っ ゚n" +                 "   (っノn" +                 "    `J");         mDatas.add("巴拉巴拉巴拉,把你变成猪!n" +                 "  ∧_∧n" +                 " (。・ω・。)つ━☆・*。n" +                 "  ⊂   ノ    ・゜+.n" +                 " しーJ   °。+ *´¨)n" +                 "            .· ´¸.·*´¨) ¸.·*¨)n" +                 "             (¸.·´ (¸.·’*");     }      public List<String> getData() {         return mDatas;     } }  
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast;  import com.example.m1571.myapplication.badgeview.Badge; import com.example.m1571.myapplication.badgeview.QBadgeView;  import java.util.List;  //实现QQ微信聊天列表信息的消息数量提示 public class ListViewActivity extends AppCompatActivity {     ListView listview;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_list_view);         listview = (ListView) findViewById(R.id.listview);         listview.setAdapter(new ListAdapter());     }      class ListAdapter extends BaseAdapter {         private List<String> data;          public ListAdapter() {             data = new DataSupport().getData();         }          @Override         public int getCount() {             return data.size();         }          @Override         public Object getItem(int position) {             return data.get(position);         }          @Override         public long getItemId(int position) {             return position;         }          @Override         public View getView(final int position, View convertView, ViewGroup parent) {             Holder holder;             if (convertView == null) {                 holder = new Holder();                 convertView = LayoutInflater.from(ListViewActivity.this).inflate(R.layout.item_view, parent, false);                 holder.textView = (TextView) convertView.findViewById(R.id.tv_content);                 holder.badge = new QBadgeView(ListViewActivity.this).bindTarget(convertView.findViewById(R.id.imageview));                 holder.badge.setBadgeTextSize(12, true);                 convertView.setTag(holder);             } else {                 holder = (Holder) convertView.getTag();             }             holder.textView.setText(data.get(position));             holder.badge.setBadgeNumber(position);             holder.badge.setOnDragStateChangedListener(new Badge.OnDragStateChangedListener() {                 @Override                 public void onDragStateChanged(int dragState, Badge badge, View targetView) {                     if (dragState == STATE_SUCCEED) {                         Toast.makeText(ListViewActivity.this, String.valueOf(position), Toast.LENGTH_SHORT).show();                     }                 }             });             return convertView;         }          class Holder {             TextView textView;             Badge badge;         }     } }  
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"     xmlns:tools="https://schemas.android.com/tools"     android:id="@+id/activity_list_view"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:paddingBottom="@dimen/activity_vertical_margin"     android:paddingLeft="@dimen/activity_horizontal_margin"     android:paddingRight="@dimen/activity_horizontal_margin"     android:paddingTop="@dimen/activity_vertical_margin"     tools:context=".ListViewActivity">      <ListView         android:id="@+id/listview"         android:layout_width="match_parent"         android:layout_height="wrap_content"/> </RelativeLayout>  
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="wrap_content">      <RelativeLayout         android:id="@+id/root"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:padding="10dp">          <ImageView             android:id="@+id/imageview"             android:layout_width="60dp"             android:layout_height="60dp"             android:layout_marginRight="10dp"             android:src="@mipmap/ic_launcher" />          <TextView             android:id="@+id/tv_time"             android:layout_width="wrap_content"             android:layout_height="30dp"             android:layout_toRightOf="@+id/imageview"             android:textSize="13sp"             android:gravity="center_vertical"             android:text="2016年8月8日 10:30:02"/>          <TextView             android:id="@+id/tv_content"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_toRightOf="@+id/imageview"             android:layout_below="@+id/tv_time"             android:textSize="15sp"             android:textColor="#333333"             android:text="(`・ω・´)ฅ铲屎官快来"/>     </RelativeLayout> </FrameLayout> 
 import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast;  import com.example.m1571.myapplication.badgeview.Badge; import com.example.m1571.myapplication.badgeview.QBadgeView;  import java.util.List;   public class RecyclerViewActivity extends AppCompatActivity {     RecyclerView recyclerView;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_recycler_view);         recyclerView = (RecyclerView) findViewById(R.id.recyclerView);         recyclerView.setLayoutManager(new LinearLayoutManager(this));         recyclerView.setAdapter(new RecyclerAdapter());     }      class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.Holder> {         private List<String> data;          public RecyclerAdapter() {             data = new DataSupport().getData();         }          @Override         public Holder onCreateViewHolder(ViewGroup parent, int viewType) {             return new Holder(LayoutInflater.from(RecyclerViewActivity.this).inflate(R.layout.item_view, parent, false));         }          @Override         public void onBindViewHolder(Holder holder, int position) {             holder.textView.setText(data.get(position));             holder.badge.setBadgeNumber(position);         }          @Override         public int getItemCount() {             return data.size();         }          class Holder extends RecyclerView.ViewHolder {             TextView textView;             Badge badge;              public Holder(View itemView) {                 super(itemView);                 textView = (TextView) itemView.findViewById(R.id.tv_content);                 badge = new QBadgeView(RecyclerViewActivity.this).bindTarget(itemView.findViewById(R.id.root));                 badge.setBadgeGravity(Gravity.CENTER | Gravity.END);                 badge.setBadgeTextSize(14, true);                 badge.setBadgePadding(6, true);                 badge.setOnDragStateChangedListener(new Badge.OnDragStateChangedListener() {                     @Override                     public void onDragStateChanged(int dragState, Badge badge, View targetView) {                         if (dragState == STATE_SUCCEED) {                             Toast.makeText(RecyclerViewActivity.this, String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();                         }                     }                 });             }         }     } } 
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
 官方软件产品操作指南 (170)
官方软件产品操作指南 (170)