Android custom component series-mask text Animation

Source: Internet
Author: User

Animation of masked text is very common in Flash. As an Android app developer, do you want to make this animation into your app? In this article, we will take a look at how to customize an ImageView to enable a text image to achieve a text mask flashing effect. Let's take a look at the effect.

(Screen recording latency may cause poor results)

I. Implementation Principle

The implementation principle is to override the onCreate method of the View. After obtaining the image resources, you can modify the transparency of each pixel. Then, start a thread to cyclically change the pixel transparency in a region.

RGBA basics: (the following sections describe text reference from Wikipedia)

RGBA is the color space that represents Red (Red) Green (Green) Blue (Blue) and Alpha. Although it is sometimes described as a color space, it is actually only the additional information attached to the RGB model. The color used is RGB and can belong to any RGB color space. However, Catmull and Smith proposed this indispensable alpha value between 1971 and 1972, this makes alpha rendering and alpha synthesis possible. The author named alpha as the Greek letter derived from the classic linear interpolation equation α A + (1-α) B.

Alpha channels are generally used as opacity parameters. If the alpha channel value of a pixel is 0%, it is completely transparent (that is, invisible ), the value 100% means a completely opaque pixel (a traditional digital image ). The value between 0% and 100% enables pixels to be displayed through the background, just like glass (translucent). This effect is not possible with simple binary transparency (transparent or opaque. It makes digital synthesis easy. The alpha channel value can be expressed as a percentage, an integer, or a real number ranging from 0 to 1 as in the RGB parameter.

Sometimes it is also written as ARGB (like RGBA, but the first data is alpha), which is the term used by Macromedia products. For example, 0x80FFFF00 is 50% transparent yellow, because all parameters are expressed in the range from 0 to 255. 0x80 is 128, which is about half of 255.

PNG is an image format that uses RGBA.

II. Specific implementation

 

Package com. example. helloworld; import android. content. context; import android. content. res. typedArray; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. canvas; import android. graphics. color; import android. graphics. matrix; import android. graphics. paint; import android. OS. handler; import android. OS. message; import android. OS. systemClock; import android. util. attribut ESet; import android. view. view; import android. widget. imageView;/*** @ author sunshine intensity **/public class SplashImageView extends ImageView {private Bitmap alterBitmap; private Canvas canvas; private Paint paint; private Handler handler; private static int START_POSITION = 20; private final int speed; private int nowPosition = START_POSITION; private static int SHOW_WIDTH = 20; private boolean isFirst = true; p Rivate boolean isStop = false; private class MyHandler extends Handler {private static final long SCALE = 10000; private static final int MSG_PAINT = 1; private final SplashImageView owner; private final int speed; private long angle; private long lastTime; public MyHandler (SplashImageView owner) {this. owner = owner; this. lastTime = SystemClock. elapsedRealtime (); this. speed = owner. speed; sendEmptyMessage (MSG_PAINT) ;}@ Overridepublic void handleMessage (Message msg) {if (msg. what = MSG_PAINT) {long now = SystemClock. elapsedRealtime (); long delta_time = now-lastTime; System. out. println ("delta_time =" + delta_time); System. out. println ("alterBitmap. width = "+ alterBitmap. getWidth (); if (nowPosition + speed> = alterBitmap. getWidth ()-START_POSITION-SHOW_WIDTH) {if (isStop) {handler. removeCallbacksAndMes Sages (null); handler = null; isStop = false; return;} else {nowPosition = START_POSITION ;}} nowPosition = nowPosition + speed; if (delta_time> 0) {if (! Repeated idraw (nowPosition) {return ;}} this. sendEmptyMessageDelayed (MSG_PAINT, 10) ;}} private boolean incluidraw (long position) {System. out. println ("nofityDrawToatal =" + position); if (position <alterBitmap. getWidth ()-START_POSITION-SHOW_WIDTH) {this. invalidate (); return true;} if (handler! = Null) {handler. removeCallbacksAndMessages (null); handler = null;} return false;} @ Overridepublic void setVisibility (int visibility) {super. setVisibility (visibility); if (visibility = View. VISIBLE) {if (handler = null) {handler = new MyHandler (this);} else {handler. removeCallbacksAndMessages (null); handler. sendEmptyMessage (MyHandler. MSG_PAINT) ;}} else {if (handler! = Null) {handler. removeCallbacksAndMessages (null); handler = null ;}} public void stopSplashAnimation () {if (handler! = Null) {isStop = true;} public SplashImageView (Context context, AttributeSet attrs) {super (context, attrs); TypedArray a = context. obtainStyledAttributes (attrs, R. styleable. fuseImageView, 0, 0); int resId =. getResourceId (R. styleable. fuseImageView_imageSrc, 0); int speed =. getInt (R. styleable. fuseImageView_speed, 5); this. speed = speed <= 0? 1: speed; Bitmap up = BitmapFactory. decodeResource (context. getResources (), resId); alterBitmap = Bitmap. createBitmap (up. getWidth (), up. getHeight (), up. getConfig (); canvas = new Canvas (alterBitmap); paint = new Paint (); paint. setStrokeWidth (5); paint. setColor (Color. BLACK); canvas. drawBitmap (up, new Matrix (), paint); setImageBitmap (alterBitmap); if (getVisibility () = View. VISIBLE) {if (handler = null) {handler = new MyHandler (this) ;}}@ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); if (isFirst) {isFirst = false; for (int I = nowPosition; I 200) {color = Color. argb (80, r, g, B);} else {color = Color. argb (a, r, g, B);} alterBitmap. setPixel (I, j, color) ;}}for (int I = nowPosition; I
 
  
START_POSITION) {for (int I = nowPosition-SHOW_WIDTH; I
  
   
(200) {color = Color. argb (80, r, g, B);} else {color = Color. argb (a, r, g, B);} alterBitmap. setPixel (I, j, color) ;}} setImageBitmap (alterBitmap );}}
  
 
Iii. Implementation Details

 

1. initialize the constructor

 

public SplashImageView(Context context, AttributeSet attrs) {super(context, attrs);TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.FuseImageView, 0, 0);int resId = a.getResourceId(R.styleable.FuseImageView_imageSrc, 0);int speed = a.getInt(R.styleable.FuseImageView_speed, 5);this.speed = speed <= 0 ? 1 : speed;Bitmap up = BitmapFactory.decodeResource(context.getResources(), resId);alterBitmap = Bitmap.createBitmap(up.getWidth(), up.getHeight(),up.getConfig());canvas = new Canvas(alterBitmap);paint = new Paint();paint.setStrokeWidth(5);paint.setColor(Color.BLACK);canvas.drawBitmap(up, new Matrix(), paint);setImageBitmap(alterBitmap);if (getVisibility() == View.VISIBLE) {if (handler == null) {handler = new MyHandler(this);}}}
The preceding TypedArray is a custom attribute. In the res/values directory, create a new attrs. xml file to add a custom attribute.

 

 

 
     
                      
  
 
Here are two custom attributes, one is the image resource ID and the other is the movement speed of the mask (in fact, the above can also inherit the self View to implement custom, I have special requirements to inherit from ImageView)

 

Then, obtain the image resources through BitmapFactory, and create a writable Bitmap resource to the Canvas through the createBitmap method, and draw the writable Bitmap to the background of the same resource.

Whether the View is visible under the interpretation View is used to determine whether the View is visible. If visible, the thread is enabled for animation, otherwise, enabling thread rendering will waste resources (because it is invisible at all ).

2. How to change transparency and draw (onDraw method)

 

for (int i = nowPosition; i < nowPosition + SHOW_WIDTH; i++) {for (int j = 0; j < alterBitmap.getHeight(); j++) {int color = alterBitmap.getPixel(i, j);int r = Color.red(color);int g = Color.green(color);int b = Color.blue(color);int a = Color.alpha(color);if (a == 80) {color = Color.argb(255, r, g, b);} else {color = Color.argb(a, r, g, b);}alterBitmap.setPixel(i, j, color);}}if (nowPosition > START_POSITION) {for (int i = nowPosition - SHOW_WIDTH; i < nowPosition; i++) {for (int j = 0; j < alterBitmap.getHeight(); j++) {int color = alterBitmap.getPixel(i, j);int r = Color.red(color);int g = Color.green(color);int b = Color.blue(color);int a = Color.alpha(color);if (a > 200) {color = Color.argb(80, r, g, b);} else {color = Color.argb(a, r, g, b);}alterBitmap.setPixel(i, j, color);}}}
The above two loops are used to draw the text. The above loop is used to draw an area to minimize the transparency of the text (255), and the text in this part is highlighted, when the text transparency of the remaining part is adjusted to 80, the background color is displayed and the text darkness is decreased.

 

3. How to move the mask cyclically

 

private class MyHandler extends Handler {private static final long SCALE = 10000;private static final int MSG_PAINT = 1;private final SplashImageView owner;private final int speed;private long angle;private long lastTime;public MyHandler(SplashImageView owner) {this.owner = owner;this.lastTime = SystemClock.elapsedRealtime();this.speed = owner.speed;sendEmptyMessage(MSG_PAINT);}@Overridepublic void handleMessage(Message msg) {if (msg.what == MSG_PAINT) {long now = SystemClock.elapsedRealtime();long delta_time = now - lastTime;System.out.println("delta_time = " + delta_time);System.out.println("alterBitmap.Width = "+ alterBitmap.getWidth());if (nowPosition + speed >= alterBitmap.getWidth()- START_POSITION - SHOW_WIDTH) {if (isStop) {handler.removeCallbacksAndMessages(null);handler = null;isStop = false;return;} else {nowPosition = START_POSITION;}}nowPosition = nowPosition + speed;if (delta_time > 0) {if (!notifiDraw(nowPosition)) {return;}}this.sendEmptyMessageDelayed(MSG_PAINT, 10);}}}
The loop movement mask is written in a thread, and the distance between the speed (configured speed) is moved every 10 milliseconds to achieve the moving effect of the mask, then, the image width is used to determine whether the image has reached the rightmost.

 

 

Summary: in fact, the above implementation principle is not difficult. The main point is to know the knowledge of RGBA and how to change the transparency of pixels. This is just a method that I have come up with for the moment. If there is any better way to achieve it, I hope I can share it with you.

In addition, "Sunshine Xiaoqiang"'s other blog article "is a man's next layer 100 [Layer 3]-Gao imitation Bank of Communications mobile client interface" participated in the CSDN blog competition, if you think these blog posts are helpful to you, hope you vote for your valuable vote, vote address: http://vote.blog.csdn.net/Article/Details? Articleid = 30101091

 

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.