[Android] Imitation of the new QQ tab below to drag the mark as read effect

Source: Internet
Author: User
Tags cos drawtext gety

The following content is original, welcome reprint, Reprint please specify

From every day blog: http://www.cnblogs.com/tiantianbyconan/p/4182929.html

Can drag the red dot, (imitate the new version qq,tab below drag and drop mark as read effect), drag a certain distance can disappear callback.

Github:draggableflagview (Https://github.com/wangjiegulu/DraggableFlagView)

Implementation principle:

The OnDraw () method is constantly called to refresh the drawing, depending on the movement of the touch event.

* Note: The original Little red dot here is called red dot A; the little red dots that are drawn according to the finger movement are called red dot B.

The logic to handle when the touch event moves:

1. The radius of the red dot a will continue to be smaller depending on the sliding distance.

2. Red dot B moves in the position immediately following the finger.

3. A Bezier curve is required between the red dot A and the red dot B to draw the connecting area.

4. If the distance between the red dot A and the red dot B reaches the maximum setting, the drag and drop will be effective, and the red dot will disappear once you let go.

5. If the 4th case is reached, the Bezier curves of the red dot A and the middle join will not be drawn.

6. If the distance between the red dot A and the red dot B does not reach the maximum distance set, then let go, the red dot b disappears, red dot a from the original radius of the smaller use bounce animation to the original state

Some tool classes need to rely on androidbucket (https://github.com/wangjiegulu/AndroidBucket), Nineoldandroid

How to use:

<com.wangjie.draggableflagview.draggableflagview xmlns:dfv= "http://schemas.android.com/apk/res/ Com.wangjie.draggableflagview "            android:id=" @+id/main_dfv "            android:layout_width=" 20DP "            android: layout_height= "20DP"            android:layout_alignparentbottom= "true"            android:layout_margin= "15DP"            DFV: Color= "#FF3B30"            />

 1 public class Mainactivity extends Activity implements Draggableflagview.ondraggableflagviewlistener, View.onclicklistener {2 3 @Override 4 public void OnCreate (Bundle savedinstancestate) {5 super.oncreate (savedinstancestate); 6 Setcontentview (R.layout.main); 7 Findviewbyid (R.ID.MAIN_BTN). Setonclicklistener (this); 8 9 Draggableflagview Draggableflagview = (draggableflagview) Findviewbyid (R.ID.MAIN_DFV); DraggableFla Gview.setondraggableflagviewlistener (This), Draggableflagview.settext ("7"),}13 @Override15 Pub LIC void Onflagdismiss (Draggableflagview view) {Toast.maketext (this, "Onflagdismiss", Toast.length_short). Show ( );}18 @Override20 public void OnClick (View v) {switch (V.getid ()) {R.ID.M         Ain_btn:23 Toast.maketext (this, "Hello World", Toast.length_short). Show (); break;25 }26}27} 

Draggableflagview Code:

  1/** 2 * Author:wangjie 3 * Email: [email protected] 4 * DATE:12/23/14. 5 */6 public class Draggableflagview extends View {7 private static final String TAG = DraggableFlagView.class.ge  Tsimplename ();          8 9 public static interface Ondraggableflagviewlistener {10/** 11 * Callback after destroying a dot 12 * 13 * @param view */Onflagdismiss (Draggableflagview view); Ondraggableflagviewlistener Ondraggableflagviewlistener;         public void Setondraggableflagviewlistener (Ondraggableflagviewlistener ondraggableflagviewlistener) {21 This.ondraggableflagviewlistener = Ondraggableflagviewlistener;     The public Draggableflagview (context context) {+ super (context); + init (context); 27 } The private int patientcolor = color.red; Public Draggableflagview (context context, AttributeSet Attrs) {(context, attrs); 33         TypedArray a = Context.obtainstyledattributes (Attrs, R.styleable.draggableflagview); Indexcount int = A.getindexcount (); for (int i = 0; i < Indexcount; i++) {attr int attrindex = A.getindex (i);             Index = = R.styleable.draggableflagview_color) {Patientcolor = A.getcolor (Attrindex, color.red); 39 } a.recycle (); Init (context); Draggableflagview (context context, AttributeSet attrs, int defstyle) { , Attrs, Defstyle); Init (context); The context context; Wuyi private int Originradius; The radius of the initial circle is the private int originwidth; originheight private int; maxmovelength private int; The largest moving elongated distance is the private Boolean isarrivedmaxmoved; Reached the maximum pull long distance (let go of triggering event) in the Curradius of the private int; The radius of the current point is the private int touchedpointradius;   The radius of the touch Circle 60  Private point startPoint = new Point (); EndPoint Private point = new Point (); The private paint paint; Draw a circular figure of the private paint textpaint; Draw a circular figure of paint.fontmetrics textfontmetrics; Int[] location; The private Boolean istouched; Is it a touch state? Triangle Triangle = new Triangle (); The private String text = ""; The text displayed in the normal state is in the form of the private void init (context context) {this.context = Context; Setbackgro Undcolor (color.transparent); 79 80//Set the paint of the flag to be painted bayi paint = new paint (); Paint.setcolor (Patientcolor); Paint.setantialias (TRUE); 84 85//Set paint for drawing text Textpaint = new paint (); Textpaint.setantialias (TRUE); Textpaint.setcolor (Color.White); Textpaint.settextsize (abtextutil.sp2px (context, 12)); Textpaint.settextalign (Paint.Align.CENTER); Textfontmetrics = paint.geTfontmetrics (); 94 Relativelayout.layoutparams ORIGINLP; The actual layoutparams relativelayout.layoutparams NEWLP; Touch Time Layoutparams 98 Private Boolean isFirst = true; @Override101 protected void onsizechanged (int w, int h, int oldw, int oldh) {102 Super.onsizechange D (W, H, OLDW, OLDH); 103//LOGGER.D (TAG, String.Format ("Onsizechanged, W:%s, H:%s, Oldw:%s, Oldh:%s", W, H, old             W, OLDH)) 104 if (IsFirst && w > 0 && H > 0) {isFirst = false;106 107 Originwidth = w;108 Originheight = h;109 Originradius = math.min (Originwidth, Originheig HT)/2;111 Curradius = originradius;112 Touchedpointradius = originradius;113 max Movelength = abapputil.getdeviceheight (context)/6;115 refreshstartpoint (); 117 118 ViewGroup. Layoutparams LP = This.getlayoutparams (); 119 if (RelaTiveLayout.LayoutParams.class.isAssignableFrom (Lp.getclass ())) {ORIGINLP = (relativelayout.layoutparam     s) lp;121}122 NEWLP = new Relativelayout.layoutparams (lp.width, lp.height); 123}124 125 }126 127 @Override128 public void Setlayoutparams (Viewgroup.layoutparams params) {129 SUPER.SETLAYOUTPA Rams (params); Refreshstartpoint (); 131}132 133/**134 * After modifying layoutparams, you need to reset startPoint135 * /136 private void Refreshstartpoint () {137 location = new int[2];138 This.getlocationinwindow (location ); 139//LOGGER.D (TAG, "location in screen:" + arrays.tostring);//Startpoint.set (locatio N[0], location[1] + h); 141 try {142 location[1] = location[1]-abapputil.gettopbarheight ((Activity) c Ontext); 143} catch (Exception ex) {144}145 146 startpoint.set (location[0], location[1] + getmeas    Uredheight ()); 147//    LOGGER.D (TAG, "startPoint:" + startPoint); 148}149 Path Path = new Path (); 151 @Override153 PR otected void OnDraw (canvas canvas) {154 super.ondraw (canvas); 155 Canvas.drawcolor (Color.transparent); 156 1 Startcirclex int = 0, Startcircley = 0;158 if (istouched) {//Touch status 159 Startcirclex = S Tartpoint.x + curradius;161 Startcircley = startpoint.y-curradius;162//Draw the original circle (the radius is constantly changing as the touch moves)             163 canvas.drawcircle (Startcirclex, Startcircley, Curradius, paint); 164//Draw finger-traced Circle 165 int endcirclex = endpoint.x;166 int Endcircley = endpoint.y;167 canvas.drawcircle (Endcirclex, en Dcircley, Originradius, paint); 168 169 if (!isarrivedmaxmoved) {//does not reach the maximum tensile value of Path.reset (); 171 Double sin = triangle.deltay/triangle.hypotenuse;172 double cos = triangle.deltax/ triangle.hypotenuse;173174//A Point 175 path.moveto (176 (float) (Startcirclex-curradius * s                  IN), 177 (float) (startcircley-curradius * cos) 178) 179//b point 180                         Path.lineto (181 (float) (Startcirclex + Curradius * sin), 182 (float)                         (Startcircley + curradius * cos) 183) 184//C-point 185 path.quadto (186 (Startcirclex + Endcirclex)/2, (Startcircley + Endcircley)/2,187 (float) (end                  Circlex + Originradius * sin), (float) (Endcircley + originradius * cos) 188); 189//D point 190                         Path.lineto (191 (float) (Endcirclex-originradius * sin), 192 (float)      (Endcircley-originradius * cos) 193) 194//A point 195 path.quadto (196                   (Startcirclex + Endcirclex)/2, (Startcircley + Endcircley)/2,197 (float) (s Tartcirclex-curradius * sin), (float) (startcircley-curradius * cos) 198); 199 CANVAS.D                 Rawpath (path, paint),}201 202 203} else {//non-touch status 204 if (Curradius > 0) {205 Startcirclex = curradius;206 Startcircley = originheight-curradius;207 Canva S.drawcircle (Startcirclex, Startcircley, Curradius, paint); 208 if (Curradius = = Originradius) {//only in return to normal Text 209//Draw text in case of float texth = Textfontmetrics.bottom-textfontmetrics.top                    ; 211 Canvas.drawtext (text, Startcirclex, Startcircley + TEXTH/2, textpaint); 212// Canvas.drawtext (text, Startcirclex, Startcircley, textpaint); 213}214}215 216}217 218//LOGGER.D (TAG, "Circlex:" + Startcirclex + ", Circley:" + Startcircley + ", Curradius:" + Curradius "; 219 220 221}222 223 float downx = float.max_value;224 float DownY = float.max_value;225 226 @Override227 public boolean Ontoucheve         NT (Motionevent event) {228 super.ontouchevent (event); 229//LOGGER.D (TAG, "ontouchevent:" + event); 230                 Switch (event.getaction ()) {231 case motionevent.action_down:232 istouched = true;233 This.setlayoutparams (NEWLP); 234 endpoint.x = (int) downx;235 Endpoint.y = (in T) downy;236 237 changeviewheight (This, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_                 PARENT); 238 postinvalidate (); 239 downx = Event.getx () + location[0];241 DownY = event.gety () + location[1];242//LOGGER.D (TAG, String.Format ("Downx:%f, DownY:%f", Downx, down             Y)); 243 244    break;245 Case motionevent.action_move:246//calculates right-angled edges and hypotenuse (used to calculate the padding between two circles to be drawn) 247 Triangle.deltax = Event.getx ()-downx;248 Triangle.deltay =-1 * (Event.gety ()-DownY); Y-axis in opposite direction, all need to take the inverse 249 double distance = math.sqrt (Triangle.deltax * triangle.deltax + triangle.deltay * tria Ngle.deltay); triangle.hypotenuse = distance;251//LOGGER.D (TAG, "triangle:" + Triangl e); 252 refreshcurradiusbymovedistance ((int) distance); 253 254 endpoint.x = (int) event.get X (); 255 endpoint.y = (int) event.gety (); 257 postinvalidate (); 258 259 B reak;260 case motionevent.action_up:261 istouched = false;262 this.setlayoutpa Rams (ORIGINLP); 263 if (isarrivedmaxmoved) {//Trigger event 265 changeviewheight (this, orig              Inwidth, originheight); 266       Postinvalidate (); 267 if (null! = Ondraggableflagviewlistener) {268 Ondr                     Aggableflagviewlistener.onflagdismiss (this); 269}270 logger.d (TAG, "triggering event ..."); 271 Resetafterdismiss (); 272} else {//restore 273 changeviewheight (this, O                 Riginwidth, originheight); 274 startrollbackanimation (500/*ms*/); 275}276 277         Downx = float.max_value;278 DownY = float.max_value;279 break;280}281 282         Return true;283}284 285/**286 * After triggering event reset 287 */288 private void Resetafterdismiss () {289 This.setvisibility (GONE); 290 text = ""; 291 isarrivedmaxmoved = false;292 Curradius = Originr adius;293 postinvalidate (); 294}295 296/**297 * Refresh the original circle radius according to the moving distance 298 *299 * @param distan ce300 */301 private void refreshcurradiusbymovedistance (int distance) {302 if (distance > maxmovelength) {303 isAr             rivedmaxmoved = true;304 Curradius = 0;305} else {306 isarrivedmaxmoved = false;307 float Calcradius = (1-1f * distance/maxmovelength) * originradius;308 float Maxradius = abtextutil. DIP2PX (context, 2); 309 Curradius = (int) Math.max (Calcradius, Maxradius); 310//LOGGER.D (TAG, "[Ref         Reshcurradiusbymovedistance]curradius: "+ Curradius +", Calcradius: "+ Calcradius +", Maxradius: "+ MaxRadius"; 311      }312 313}314 315 316/**317 * Change the height of a control 318 *319 * @param view320 * @param height321 */322 private void Changeviewheight (view view, int width, int height) {323 viewgroup.layoutparams LP = VIEW.G         Etlayoutparams (); 324 if (NULL = = LP) {325 LP = originlp;326}327 lp.width = width;328 Lp.height = Height;329 VIEW.SETLAYOUTPARAMS (LP); 330}331 332/**333 * Rollback State animation 334 */335 Private Valueanimator             rollbackanim;336 337 private void startrollbackanimation (long duration) {338 if (null = = Rollbackanim) {339  Rollbackanim = Valueanimator.offloat (Curradius, Originradius); 340 Rollbackanim.addupdatelistener (New Valueanimator.animatorupdatelistener () {341 @Override342 public void Onanimationupdate (Va                     Lueanimator animation) {343 Float value = (float) animation.getanimatedvalue (); 344             Curradius = (int) value;345 postinvalidate (); 346}347}); 348 Rollbackanim.setinterpolator (New Bounceinterpolator ());                 Bounce Effect 349 Rollbackanim.addlistener (new Animatorlisteneradapter () {@Override351 public void Onanimationend (Animator animation) {352 Super.onanimAtionend (animation); 353 DraggableFlagView.this.clearAnimation (); 354}355} ); 356}357 rollbackanim.setduration (duration); 358 Rollbackanim.start (); 359}360 361 362/*         *363 * Calculates the triangular edge relationship of four coordinates 364 */365 class Triangle {366 double deltax;367 double deltay;368                     Double hypotenuse;369 370 @Override371 public String toString () {372 return "triangle{" +373 "deltax=" + deltax +374 ", deltay=" + DeltaY +375 ", Hypotenus E= "+ hypotenuse +376 '} '; 377}378}379 380 public String GetText () {381 retur N text;382}383 384 public void SetText (String text) {385 This.text = text;386 postinvalidate (); 38 7}388}

[Android] Imitation of the new QQ tab below to drag the mark as read effect

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.