Android Imitation jingdong home page carousel text effect _android

Source: Internet
Author: User
Tags drawtext string back

Jingdong client's Carousel text effect:

This secondary implementation is only the following scrolling text (in front of the ImageView or TextView implementation can), look at the effect of implementation


Realize the idea


The above figure is just a general idea, to achieve also need to improve more details, the following will be step-by-step to achieve this effect:

1. Package data Source: from the picture can be seen, the rotation of the text is divided into two parts, for the moment they are called prefixes and content, and the actual use of the process to click on the carousel map must be jump page, and most should be webview, If we want to set the click Time to get the content is a link, then the structure of the data source is very clear


Create ADEnity a class and refine some basic methods, the following code

public class Adenity {
 private string Mfront;//Previous Text
 private string mback;//Back Text
 private string Murl;//Package Contains links public

 adenity (string mfront, String mback,string murl) {
  this.mfront = Mfront;
  This.mback = Mback;
  This.murl = Murl;
 }

 Public String Getmurl () {return
  murl;
 }

 public void Setmurl (String murl) {
  this.murl = Murl;
 }

 Public String Getmfront () {return
  mfront;
 }

 public void Setmfront (String mfront) {
  this.mfront = Mfront;
 }

 Public String Getmback () {return
  mback;
 }

 public void Setmback (String mback) {
  this.mback = mback;
 }
}

2. The next step is to customize this custom view, first to sort out the idea and look at a construction diagram


All of the parameters to implement this custom view are listed in the table above, most of the parameters are easy to understand, the individual parameters are necessary to add, such as whether to initialize the ordinate into the text, whether the text is moving in the two parameters, after the content will be described in detail. Before you draw, you need to know a little bit about the basics, the way you draw text, and there's a lot of detail to deal with.

Methods are better understood, draw the specified string (you can specify a range) at the coordinates ( x , y ) , but x,y not what we understand should be the coordinates of the upper-left corner of the text. The x coordinates are based on Paint the properties that can be transformed, and the default x is the left coordinate of the text, if Paint Set paint.setTextAlign(Paint.Align.CENTER) ; that is the central position of the character. Y Coordinates are the coordinates of the text baseline y . Baseline about drawing text:

Let's talk in a diagram.

The Blue line in the figure is baseline , you can see that he is neither the top coordinates nor the bottom coordinates, then when we draw the text must be the hope to draw the text in the middle. This is the time to introduce paint.getTextBound() getTextBounds(String text, int start, int end, Rect bounds) a method, pass in an Rect object, When this method is called, the Rect object is populated, and the filled content is the offset coordinate of the drawn text, and the coordinates of the baseline rect are baseline plotted as follows:


But in fact his value (2,-25,76,3) is only, is relative to the position of baseline, drawing a picture will better understand

To draw the text in the middle then the actual drawing of the baseline coordinate should be the center of the component plus the center of the text, which is the offset of the middle coordinate of the frame relative to the baseline "> so to draw the text in the middle, The coordinates of the actual drawing baseline should be the center of the assembly, plus the offset value of the text center (the middle coordinate of the frame in the diagram) relative to the baseline


In this picture, you should understand the relationship between the coordinates of the actual drawn text and the central coordinates of the Assembly. With respect to the calculation of the offset value, the conventional method of geometric calculation should be the absolute ==baseline coordinate of the center coordinate + offset value of the component (i.e. the actual plotted coordinates), However, because the coordinates of the box are calculated relative to the baseline, top is negative, botton is positive, then this offset value can be directly used (Top+bottom)/second, can not read the classmate could draw a sketch, with top=-25,bottom=3 to calculate, See if the results are consistent.
With the above understanding, the way we draw the correct text is determined
Got the height of the component int mheight, text frame rect bound case

Draw text in the middle

 MHEIGHT/2-(bound.top + bound.bottom)/2
//In the ordinate for my place to draw text
//calculation method
//MHEIGHT/2 = my + (bound.top + bound.bo Ttom)/2;

Text scrolling to the highest point

my = = 0-bound.bottom
//In the ordinate for my place to draw, at this time the text just moved to the highest point
//Calculation mode
//my + bound.bottom = 0;

Text scrolls to the lowest point and just rolls out of the component

 my = Mheight-indexbound.top;
In the ordinate for my place to draw, when the text just moved to the highest point
//Calculation mode
//my + bound.top = mheight;

Knowing how to correctly draw the coordinates of the text and boundary conditions, the following is the steps to draw the text
Initialize data first, set default values

Initialize default value
private void init () {
 mduration =;
 Minterval = 1000;
 Mindex = 0;
 Mpaintfront = new Paint ();
 Mpaintfront.setantialias (true);
 Mpaintfront.setdither (true);
 Mpaintfront.settextsize (a);


 Mpaintback = new Paint ();
 Mpaintback.setantialias (true);
 Mpaintback.setdither (true);
 Mpaintback.settextsize (a);



As we know in the preceding narrative, when you first enter the text should be at the bottom of the component, but this value is required to get the height of the component and the current display text to judge, so should be placed in the OnDraw to initialize this value, so you need to initialize the previous properties, to determine when the my== 0 and assigns my value when uninitialized.
The next step is OnDraw.

Get the current data

Gets the current data
adenity model = Mtexts.get (mindex);
String font = Model.getmfront ();
String back = Model.getmback ();
Draw the outer frame of the prefix
Rect indexbound = new Rect ();
Mpaintfront.gettextbounds (font, 0, font.length (), indexbound);

Draw the outer frame of the content
Rect contentbound = new Rect ();
Mpaintback.gettextbounds (back, 0, Back.length (), contentbound);

Initialization of my

if (i = = 0 && Hasinit = = False) {My
 = Getmeasuredheight ()-indexbound.top;
 Hasinit = true;
}

Treatment of boundary conditions
/

/move to top if (my = = 0-indexbound.bottom) {log.i (TAG, "OnDraw:" + getmeasuredheight ()); my = Getmeasuredheight ()-indexbound.top;//back to bottom mindex++;//replace a set of data}//Move to middle if (my = = Getmeasuredheight ()/2-(Indexbo
 Und.top + indexbound.bottom)/2 {ismove = false;//Stop Moving Timer timer = new timer (); 
  Timer.schedule (New TimerTask () {@Override public void run () {postinvalidate ();//notification Redraw ismove = true;//Set Move to True }, Minterval); How many milliseconds to pause and then move again the processing of the move and the processing of the data source my-= 1;//moves only one pixel at a time, ensuring smooth display//Recycle data if (Mindex = = Mtexts.size ()) {MI
Ndex = 0; //If it is moving, the delay draw//calculation formula is a scale, the height of the component is moved at a time interval, how many milliseconds to move the 1 pixel if (ismove) {postinvalidatedelayed (Mduration/
Getmeasuredheight ());

The processing of the logic is complete and the next step is to set the Click event public interface Onclicklitener {public void OnClick (String murl);}

Private Onclicklitener Onclicklitener; public void Setonclicklitener (Textviewad.onclicklitener onclicklitener) {this.onclicklitener = OnClickLitener;}// Override the Ontouchevent event and return True to indicate that the current click event is handled by the component itself @Override PUBlic boolean ontouchevent (Motionevent event) {int action = event.getaction (); Switch (action) {case Motionevent.action_down://Call callback, pass a link to the current data source if (Onclicklitener!= null) {Onclickliten
   Er.onclick (Mtexts.get (Mindex). Getmurl ());
 } break;
return true;

Exposes settings for some other properties/set data source public void setmtexts (List mtexts) {this.mtexts = mtexts;}

Set the pause time for ad text public void setminterval (int minterval) {this.minterval = Minterval;}

Sets the length of the text from the time it appears to disappear the long public void setmduration (int mduration) {this.mduration = mduration;}

Sets the text color of the prefix public void setfrontcolor (int mfrontcolor) {mpaintfront.setcolor (mfrontcolor);}
Sets the color of the body content public void Setbackcolor (int mbackcolor) {mpaintback.setcolor (mbackcolor);} Interested students can set these properties to the Attrs.xml file and then you can set the properties in the layout file, here is not demonstrated, because I feel that each copy of this view also have to copy the XML file is more trouble, after all as there is automatic completion, It is convenient to see the method exposed outside.
(personal feelings only).

Paste the complete Adtextview code, easy to view the package com.qiyuan.jindongshangcheng.view;
Import Android.content.Context;
Import Android.graphics.Canvas; Import AndroId.graphics.Paint;
Import Android.graphics.Rect;
Import Android.util.AttributeSet;
Import Android.util.Log;
Import android.view.MotionEvent;

Import Android.widget.TextView;

Import com.qiyuan.jindongshangcheng.enity.ADEnity;
Import java.util.List;
Import Java.util.Timer;

Import Java.util.TimerTask;
 /** * Created by Huanghaojie on 2016/9/30. * * public class Textviewad extends TextView {private int mduration;//text from appearing to show disappearing time private int minterval;//text stays in the middle Time to switch between private list<adenity> mtexts; Display text data source private int my = 0; The y-coordinate of the text is private int mindex = 0; The current data subscript private Paint mpaintback; Draw the contents of the brush private Paint mpaintfront; Draw the prefix of the brush private Boolean ismove = true;
 Whether the text moves private String TAG = "Adtextview"; 
 Private Boolean hasinit = false;//whether to initialize the ordinate public interface Onclicklitener {public void OnClick (String murl) of text when it is just entered;

 Private Onclicklitener Onclicklitener; public void Setonclicklitener (Textviewad.onclicklitener onclicklitener) {This.onclickLitener = Onclicklitener;
 The public Textviewad {This (context, NULL);
  Public Textviewad (context, AttributeSet attrs) {Super (context, attrs);
 Init (); //Rewrite the Ontouchevent event and return True to indicate that the current click event is handled by the component itself @Override public boolean ontouchevent (Motionevent event) {Int act

  Ion = Event.getaction (); Switch (action) {case Motionevent.action_down://Call callback, pass a link to the current data source if (Onclicklitener!= null) {Onclickl
    Itener.onclick (Mtexts.get (Mindex). Getmurl ());
  } break;
 return true;
 //Set data source public void setmtexts (List mtexts) {this.mtexts = mtexts;
 //Set pause time for ad text public void setminterval (int minterval) {this.minterval = Minterval;
 }//sets the length of the text from the time it appears to the vanishing setmduration (int mduration) {this.mduration = mduration;
 }//Set the text color of the prefix public void setfrontcolor (int mfrontcolor) {mpaintfront.setcolor (mfrontcolor); }//Set the color of the body content public void Setbackcolor (int mbackcolor) {mpaintback.setcolor (mbackcolor);
 }//initialize default value private void init () {mduration = 500;
  Minterval = 1000;
  Mindex = 0;
  Mpaintfront = new Paint ();
  Mpaintfront.setantialias (TRUE);
  Mpaintfront.setdither (TRUE);


  Mpaintfront.settextsize (30);
  Mpaintback = new Paint ();
  Mpaintback.setantialias (TRUE);
  Mpaintback.setdither (TRUE);

 Mpaintback.settextsize (30);
  @Override protected void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH);
 LOG.I (TAG, "onsizechanged:" + h);
   } @Override protected void OnDraw (Canvas Canvas) {if (mtexts!= null) {LOG.I (TAG, "OnDraw:" + my);
   Gets the current data adenity model = Mtexts.get (Mindex);
   String font = Model.getmfront ();
   String back = Model.getmback ();
   Draw the outer frame of the prefix Rect indexbound = new Rect ();

   Mpaintfront.gettextbounds (font, 0, font.length (), indexbound);
   Draw the outer frame of the content Rect Contentbound = new Rect ();
   Mpaintback.gettextbounds (back, 0, Back.length (), contentbound); The text should be at the bottom of the component at the beginning of the entry, but this value is needed to getThe height of the component is judged by the situation of the current display text,//So it should be placed inside the OnDraw to initialize the value, so the previous initialization attribute is required to determine the assignment to my my==0 when it is not initialized.
    if (i = = 0 && Hasinit = = False) {my = Getmeasuredheight ()-indexbound.top;
   Hasinit = true;
    //Move to top if (my = = 0-indexbound.bottom) {log.i (TAG, "OnDraw:" + getmeasuredheight ()); my = Getmeasuredheight ()-indexbound.top;//returns to the bottom mindex++;//to replace a set of data} canvas.drawtext (back, 0, Back.length (), (in
   Dexbound.right-indexbound.left) +, My, mpaintback);
   Canvas.drawtext (font, 0, font.length (), my, mpaintfront); Move to middle if (my = = Getmeasuredheight ()/2-(indexbound.top + indexbound.bottom)/2) {Ismove = false;//stop Moving T
    Imer timer = new timer (); Timer.schedule (New TimerTask () {@Override public void run () {postinvalidate ();//notification Redraw Ismove = True
   ;/set move to True}}, Minterval//pause how many milliseconds to move again}//Mobile processing and data source processing my---1;//moves only one pixel at a time, as much as possible to ensure smooth display//cyclic use of data if (Mindex = = Mtexts.size ()) {Mindex = 0; ///If you are moving, then the calculation formula is deferred to a scale, one time interval moves the component height, then how many milliseconds to move the 1 pixel if (ismove) {postinvalidatedelayed (mduration/ge
   Tmeasuredheight ());
How do I use it}}}? 1, this custom control is now introduced into the XML file <?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android= "http://"
 Schemas.android.com/apk/res/android "android:layout_width=" match_parent "android:layout_height=" Match_parent "
  android:orientation= "vertical" > <com.qiyuan.jindongshangcheng.view.textviewad android:id= "@+id/textad" Android:layout_width= "Match_parent" android:layout_height= "Wrap_content"/> </LinearLayout> 2.
 Use/** * Created by Huanghaojie in Mainactivity in 2016/9/30.
 * * Public class Mainactivity extends activity {private Textviewad Textviewad;

 Private list<adenity> mlist;
  @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
  Setcontentview (R.LAYOUT.ACTIVITY_MAIN4);
  Textviewad = (Textviewad) Findviewbyid (R.id.textad); Mlist = nEW arraylist<> ();
   for (int i = 0; i < i++) {adenity adenity = new Adenity ("prefix" + I, "suffix" + I, "http://www.baidu.com" +i);
  Mlist.add (adenity);
  } textviewad.setmtexts (Mlist);
  Textviewad.setfrontcolor (color.red);
  Textviewad.setbackcolor (Color.Blue);
  Textviewad.setmduration (1000);
  Textviewad.setminterval (1000); Textviewad.setonclicklitener (New Textviewad.onclicklitener () {@Override public void OnClick (String murl) {Toas
   T.maketext (Mainactivity.this, "clicked" +murl,toast.length_long). Show ();
 }
  });
 }
}

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.