Android Custom view to realize the case analysis of the vertical horse lamp effect _android

Source: Internet
Author: User
Tags drawtext

First, we give the effect chart of the Happy Lantern

The color block in the middle is due to the distortion caused by the video turned into GIF, which automatically ignores ha.
As you all know, the horizontal horse light Android with the TextView can be achieved, details please Baidu "Android happy Lights effect." But the vertical horse-lamp effect of native Android is not supported. Online also has a lot of users to achieve the custom effect, but I always do not like to see other people's code, so this blog idea is entirely my own idea ha.

First, we need to comb the pattern for our custom controls, as shown in the following illustration:

1. First, we divide the control into three blocks, the green part of which disappears the invisible block, the middle black part is the visible area, the following red part is to appear invisible area. The Blue line represents the entire control's online and offline.
2, first we only give two pieces of text in memory, respectively, is the black part of the visible block and the red part of the desire to appear block.
3, find out the width of these blocks, height and the center point of the coordinate value.
4, when scrolling, dynamically changing the center of each block y coordinate, so that the upward translation.
5, when the translation is finished, the visible block is located in the invisible block to disappear, the visible block to appear in the visible area of the block of text. At this point, you will disappear the text block to remove the list, and reset the index of the text and center of gravity coordinates, rejoin the list, refresh.
6, with a handler to process the animation interval time. The animated effect of translation is realized by using the attribute animation Valueanimator.

The following starts with the code to explain, first of all, set some general properties with the chain setting method:

<span style= "FONT-SIZE:14PX;" > Public verticalmarqueeview color (int color) {
  This.color = color;
  return this;
 }
 
 Public Verticalmarqueeview textsize (int textsize) {
  this.textsize = textsize;
  return this;
 }
 
 Public Verticalmarqueeview datas (string[] datas) {
  this.datas = datas;
  return this;
 }
 
 public void Commit () {
  if (This.datas = null | | datas.length = 0) {
   log.e ("Verticalmarqueeview", "the Datas ' Le Ngth is illegal ");
   throw new IllegalStateException ("May is not invoke the method named Datas (string[])");
  Paint.setcolor (color);
  Paint.settextsize (TEXTSIZE);
 } </span>

Finally, make sure to call the Commit method to commit, and you can see from the code that there is the most important step in addition to the evacuation measures: set the font size.
Then I abstracted a bean class for a chunk of text:

 public class TextBlock {private int width;
  private int height;
  private String text;
  private int drawx;
  private int Drawy;
  Private Paint Paint;
  
  private int position;
   public TextBlock (int width, int height, Paint Paint) {this.width = width;
   This.height = height;
  This.paint = paint;
  public void Reset (int centery) {Reset (text, CenterX, centery, position);
  public void Reset (String text, int centery) {Reset (text, CenterX, centery, position);
  public void Reset (String text, int centery, int position) {Reset (text, CenterX, centery, position);
   public void Reset (String text, int centerx, int centery, int position) {this.text = text;
   This.position = position;
   int measurewidth = (int) paint.measuretext (text);
   DRAWX = (width-measurewidth)/2;
   FontMetrics metrics = Paint.getfontmetrics ();
  Drawy = (int) (CenterY + (metrics.bottom-metrics.top)/2-metrics.bottom); public int getPosition () {RETUrn position;
  } public void Draw (Canvas Canvas) {canvas.drawtext (text, drawx, Drawy, paint); }
 }

This bean class, the most important method is a few overloaded reset methods, by changing the value of CenterY, to dynamically change the starting point of the drawing text to achieve center drawing. About the Text Center drawing please refer to Baidu "Android Canvas Center draw text". The
is then overridden by the Onmeasure method  

 @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {sup
  Er.onmeasure (Widthmeasurespec, Heightmeasurespec);
   if (This.datas = null | | this.datas.length = = 0) {log.e ("Verticalmarqueeview", "the datas ' s length is illegal");
  Return
  width = measurespec.getsize (widthmeasurespec)-Getpaddingleft ()-getpaddingright ();
  Height = measurespec.getsize (heightmeasurespec)-getpaddingtop ()-Getpaddingbottom ();
  CenterX = WIDTH/2;
  CenterY = HEIGHT/2;
  Blocks.clear ();
  Add a block of text to the display area TextBlock block1 = new TextBlock (width, height, paint);
  Block1.reset (Datas[0], CenterX, centery, 0);
  Blocks.add (BLOCK1);
   if (Datas.length > 1) {TextBlock Block2 = new TextBlock (width, height, paint);
   Block2.reset (Datas[1], CenterX, centery + height, 1);
  Blocks.add (BLOCK2); }
 }

In this method, you first make a non-empty decision to avoid a fatal logic error. The width and center coordinates of the entire control are then obtained. Then instantiate two blocks of text TextBlock, the first block of text through reset set the midpoint y coordinates for the entire control's midpoint y coordinates, the second text block by reset set the midpoint y coordinates for centery+height, meaning is placed in the next block of text in the invisible area.
Then there is the OnDraw method, which is very simple and has given the business logic to the TextBlock draw method.

 @Override
 protected void OnDraw (Canvas Canvas) {for
  (int i = 0; i < blocks.size (); i++) {
   blocks.get (i). Draw (canvas);
  }
 

The key is the implementation of the scrolling effect, first we give two methods, start scrolling and end scrolling.

 public void Startscroll () {
  isstopscroll = false;
  if (datas = null | | datas.length = = 0 | | | datas.length = 1) {
   log.e ("Verticalmarqueeview", "the datas ' s length is Illeg Al ");
   return;
  }
  if (!isstopscroll) {
   handler.postdelayed (new Runnable () {
    
    @Override public
    void Run () {
     scroll ();
     if (!isstopscroll) {
      handler.postdelayed (this, duration_scroll);
     }}}
   , duration_scroll);
  }
 Public
 
 void Stopscroll () {
  this.isstopscroll = true;
 }

The principle is very simple, first gives a Boolean sign isstopscroll. The handler postdelayed method is then used to loop the delay to invoke the scroll method for scrolling. Next, we give the most important method of the whole text, scroll method.

private void Scroll () {Valueanimator animator = Valueanimator.ofpropertyvaluesholder (Propertyvaluesholder.ofint ("
  Scrolly ", CenterY, Centery-height));
  Animator.setduration (Duration_animator); Animator.addupdatelistener (New Animatorupdatelistener () {@Override public void onanimationupdate (Valueanimator a
    nimation) {int scrolly = (int) animation.getanimatedvalue ("scrolly");
    Blocks.get (0). Reset (scrolly);
    Blocks.get (1). Reset (scrolly + height);
   Invalidate ();
  }
  });
   
   Animator.addlistener (New Animatorlistener () {@Override public void Onanimationstart (animator animation) {} @Override public void Onanimationrepeat (animator animation) {} @Override public void Onanimationend (A
    Nimator animation) {//Remove the first int position = Blocks.get (1). GetPosition ();
    TextBlock TextBlock = blocks.remove (0);
    The last if (position = = datas.length-1) {position = 0;
    }else{position + +; } textblock.reset (datas[Position], CenterY + height, position);
    Blocks.add (TextBlock);
   Invalidate ();
  @Override public void Onanimationcancel (animator animation) {}});
 Animator.start (); }

First, the Valueanimator class is used to animate the property, starting with the midpoint y-coordinate of the control, and the ending value is centery-height, meaning to move a block of text from the bottom to the distance. Then, in the animation update callback method, the Reset method is done on the text block. When the animation is finished, get the position value of the second text block, then remove the first block of text, reset the index value of the text block, and add it to the list container. So follow the bad.
Finally, return position to a get method.

 public int getcurrentposition () {
  if (datas = null | | datas.length = = 0) {
   return-1;
  }
  if (datas.length = = 1 && blocks.size () = = 1) {return
   0;
  }
  Return Blocks.get (0). GetPosition ();
 }

All of the code for this custom control is presented above, given the relatively fragmented, where all the code is printed:

/** * @FileName: Verticalmarqueeview.java * @Author * @Description: * @Date July 13, 2016 morning 9:32:27 * @CopyRight CNP C

Orporation * * Package cc.wxf.component;
Import Android.animation.Animator;
Import Android.animation.Animator.AnimatorListener;
Import Android.animation.PropertyValuesHolder;
Import Android.animation.ValueAnimator;
Import Android.animation.ValueAnimator.AnimatorUpdateListener;
Import Android.content.Context;
Import Android.graphics.Canvas;
Import Android.graphics.Color;
Import Android.graphics.Paint;
Import Android.graphics.Paint.FontMetrics;
Import Android.os.Handler;
Import Android.util.AttributeSet;
Import Android.util.Log;

Import Android.view.View;
Import java.util.ArrayList;

Import java.util.List;
 public class Verticalmarqueeview extends view{public static final int duration_scroll = 3000;
 public static final int duration_animator = 1000;
 private int color = Color.Black;
 private int textsize = 30;
 
 Private string[] datas = null;
private int width; private int height;
 private int CenterX;
 
 private int centery;
 Private list<textblock> blocks = new arraylist<textblock> (2);
 Private Paint Paint = new Paint (Paint.anti_alias_flag);
 Private Handler Handler = new Handler ();
 
 Private Boolean isstopscroll = false; 
 Public Verticalmarqueeview (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr);
 Public Verticalmarqueeview (context, AttributeSet attrs) {Super (context, attrs);
 Public Verticalmarqueeview {Super (context);
  public Verticalmarqueeview color (int color) {this.color = color;
 return this;
  Public Verticalmarqueeview textsize (int textsize) {this.textsize = Textsize;
 return this;
  Public Verticalmarqueeview datas (string[] datas) {this.datas = datas;
 return this; public void commit () {if (This.datas = null | | datas.length = 0) {log.e ("Verticalmarqueeview", "the Datas ' s Len
   Gth is illegal "); Throw nEW IllegalStateException ("May is not invoke the method named Datas (string[)");
  } paint.setcolor (color);
 Paint.settextsize (TEXTSIZE); @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec,
  HEIGHTMEASURESPEC);
   if (This.datas = null | | this.datas.length = = 0) {log.e ("Verticalmarqueeview", "the datas ' s length is illegal");
  Return
  width = measurespec.getsize (widthmeasurespec)-Getpaddingleft ()-getpaddingright ();
  Height = measurespec.getsize (heightmeasurespec)-getpaddingtop ()-Getpaddingbottom ();
  CenterX = WIDTH/2;
  CenterY = HEIGHT/2;
  Blocks.clear ();
  Add a block of text to the display area TextBlock block1 = new TextBlock (width, height, paint);
  Block1.reset (Datas[0], CenterX, centery, 0);
  Blocks.add (BLOCK1);
   if (Datas.length > 1) {TextBlock Block2 = new TextBlock (width, height, paint);
   Block2.reset (Datas[1], CenterX, centery + height, 1);
  Blocks.add (BLOCK2); }} @Override protected void OnDraw (Canvas Canvas) {for (int i = 0; i < blocks.size (); i++) {Blocks.get (i). Draw (Canvas);
  } public void Startscroll () {isstopscroll = false; if (datas = null | | datas.length = = 0 | | | datas.length = 1) {LOG.E ("Verticalmarqueeview", "the datas ' s length is Illega
   L ");
  Return
     } if (!isstopscroll) {handler.postdelayed (new Runnable () {@Override public void run () {scroll ();
     if (!isstopscroll) {handler.postdelayed (this, duration_scroll);
  }}, Duration_scroll);
 The public void Stopscroll () {this.isstopscroll = true; private void Scroll () {Valueanimator animator = Valueanimator.ofpropertyvaluesholder (Propertyvaluesholder.ofint ("SC
  RollY ", CenterY, Centery-height));
  Animator.setduration (Duration_animator); Animator.addupdatelistener (New Animatorupdatelistener () {@Override public void onanimationupdate (Valueanimator a nimation) {int scrolly = (int) animation.getanimatedvalue ("scrolly");
    Blocks.get (0). Reset (scrolly);
    Blocks.get (1). Reset (scrolly + height);
   Invalidate ();
  }
  });
   
   Animator.addlistener (New Animatorlistener () {@Override public void Onanimationstart (animator animation) {} @Override public void Onanimationrepeat (animator animation) {} @Override public void Onanimationend (A
    Nimator animation) {//Remove the first int position = Blocks.get (1). GetPosition ();
    TextBlock TextBlock = blocks.remove (0);
    The last if (position = = datas.length-1) {position = 0;
    }else{position + +;
    } textblock.reset (Datas[position], centery + height, position);
    Blocks.add (TextBlock);
   Invalidate ();
  @Override public void Onanimationcancel (animator animation) {}});
 Animator.start ();
  public int GetCurrentPosition () {if (datas = = NULL | | | datas.length = 0) {return-1;
  } if (datas.length = = 1 && blocks.size () = = 1) {return 0; Return Blocks.get (0). Getposition ();
  public class TextBlock {private int width;
  private int height;
  private String text;
  private int drawx;
  private int Drawy;
  Private Paint Paint;
  
  private int position;
   public TextBlock (int width, int height, Paint Paint) {this.width = width;
   This.height = height;
  This.paint = paint;
  public void Reset (int centery) {Reset (text, CenterX, centery, position);
  public void Reset (String text, int centery) {Reset (text, CenterX, centery, position);
  public void Reset (String text, int centery, int position) {Reset (text, CenterX, centery, position);
   public void Reset (String text, int centerx, int centery, int position) {this.text = text;
   This.position = position;
   int measurewidth = (int) paint.measuretext (text);
   DRAWX = (width-measurewidth)/2;
   FontMetrics metrics = Paint.getfontmetrics ();
  Drawy = (int) (CenterY + (metrics.bottom-metrics.top)/2-metrics.bottom); } public int GetpositiOn () {return position;
  } public void Draw (Canvas Canvas) {canvas.drawtext (text, drawx, Drawy, paint);

 }
 }
 
}

The

Finally gives the method used, very simple.

Package Cc.wxf.androiddemo;
Import android.app.Activity;
Import Android.content.Context;
Import Android.os.Bundle;
Import Android.view.View;

Import Android.widget.Toast;

Import Cc.wxf.component.VerticalMarqueeView;

 public class Mainactivity extends activity {private Verticalmarqueeview Vmview;
  @Override public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);

  Setcontentview (R.layout.activity_main);
  Vmview = (Verticalmarqueeview) Findviewbyid (R.id.vmview);
  string[] datas = new string[]{"The South China Sea is beginning to become turbulent again", the Philippines is all over the place "," This time for a trial of waste paper, the Philippines put in a lot of cost, "test Data 4", "test data 5 for the length is not the same", "This is the test data bar"
  }; Vmview.color (Getresources (). GetColor (Android).
  R.color.black)). Textsize (sp2px (This)). Datas (Datas). commit ();
  Vmview.startscroll (); Vmview.setonclicklistener (New View.onclicklistener () {@Override public void OnClick (View v) {Toast.maketext (Mai
   Nactivity.this, "The current index is:" + vmview.getcurrentposition (), Toast.length_short). Show ();
 }
  }); }

 private int sp2px (context context, int sp) {float density = context.getresources (). Getdisplaymetrics (). scaleddensity;
 return (int) (SP * density + 0.5f);
  } @Override protected void OnDestroy () {Super.ondestroy ();
 Must be called, otherwise there will be infinite loops in memory vmview.stopscroll ();

 }
}

Demo is not available, custom view is only one of the above files.

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.