Keywords: Random fly in/out effect, keywords fly in effect
Someone asked me again today, right? I found a backup in the online storage.
In fact, I also found it online, but I am sorry for the unknown source.
Figure:
Http://blog.csdn.net/onlyonecoder/article/details/8518148
Layout File
<? Xml version = "1.0" encoding = "UTF-8"?> <RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" android: layout_width = "match_parent" android: layout_height = "match_parent" android: orientation = "vertical"> <com. hnxiaohu. huamu. widget. keywordsFlow android: id = "@ + id/keywordsflow_Layout" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: layout_abve = "@ + id/button1" android: layout_alignParentTop = "true"> </com. hnxiaohu. huamu. widget. keywordsFlow> <Button android: id = "@ + id/button1" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_alignParentBottom = "true" android: layout_alignParentLeft = "true" android: onClick = "onClick" android: text = ""/> <Button android: id = "@ + id/button2" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_alignParentBottom = "true" android: layout_toRightOf = "@ + id/button1" android: onClick = "onClick" android: text = ""/> </RelativeLayout>
Example
Package com. hnxiaohu. huamu. ui; import java. util. random; import android. app. activity; import android. OS. bundle; import android. view. view; import android. view. view. onClickListener; import android. widget. textView; import android. widget. toast; import com. hnxiaohu. huamu. r; import com. hnxiaohu. huamu. widget. keywordsFlow; public class KeywordsFlowDemo extends Activity implements OnClickListener {public static final String [] keywords = {"International trade 360", "Renmin Road", "Dashiqiao", "xintong bridge", "zijingshan ", "School of Medicine", "Erqi square", "Bisha gang", "Arc de excited door", "Juyi International", "department store", "gymnasium", "Sa cun", "Liu Zhuang ", "Chen Zhai", "technology market", "Railway Station"}; public static final String [] keywords2 = {"hot pot", "snacks", "coffee", "Cinema ", "KTV", "Teahouse", "foot bath", "massage", "Supermarket", "bank", "hotel", "Supermarket", "Henan food", "Sichuan food ", "Cake Shop", "hospital", "bakery", "mall", "Bookstore", "barbecue", "seafood", "halal"}; private KeywordsFlow keywordsFlow; public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. keywordsflow); keywordsFlow = (KeywordsFlow) findViewById (R. id. keywordsflow_Layout); keywordsFlow. setDuration (800l); keywordsFlow. setOnClickListener (this);} // fill in the keyword private void feedKeywordsFlow (KeywordsFlow keywordsFlow, String [] arr) {Random random = new Random (); for (int I = 0; I <KeywordsFlow. MAX; I ++) {int ran = random. nextInt (arr. length); String tmp = arr [ran]; keywordsFlow. feedKeyword (tmp) ;}@overridepublic void onClick (View v) {if (v. getId () = R. id. button1) {keywordsFlow. rubKeywords (); feedKeywordsFlow (keywordsFlow, keywords); keywordsFlow. go2Show (KeywordsFlow. ANIMATION_IN); return;} if (v. getId () = R. id. button2) {keywordsFlow. rubKeywords (); feedKeywordsFlow (keywordsFlow, keywords2); keywordsFlow. go2Show (KeywordsFlow. ANIMATION_OUT); return;} if (v instanceof TextView) {String keyword = (TextView) v ). getText (). toString (); Toast. makeText (getApplication (), keyword, Toast. LENGTH_SHORT ). show (); return ;}}}
Custom View
Package com. hnxiaohu. huamu. widget; import java. util. using list; import java. util. random; import java. util. vector; import android. content. context; import android. graphics. paint; import android. util. attributeSet; import android. util. typedValue; import android. view. gravity; import android. view. view; import android. view. viewTreeObserver. onGlobalLayoutListener; import android. view. animation. alphaAnimation; import Ndroid. view. animation. animation; import android. view. animation. animation. animationListener; import android. view. animation. animationSet; import android. view. animation. animationUtils; import android. view. animation. interpolator; import android. view. animation. scaleAnimation; import android. view. animation. translateAnimation; import android. widget. frameLayout; import android. widget. textView;/*** animation effects of entering and exiting keywords */ Public class KeywordsFlow extends FrameLayout implements attributes {public static final int IDX_X = 0; public static final int IDX_Y = 1; public static final int IDX_TXT_LENGTH = 2; public static final int IDX_DIS_Y = 3; /** from the outside to the inside of the animation. */Public static final int ANIMATION_IN = 1;/** animation from inner to outer. */Public static final int ANIMATION_OUT = 2;/** displacement animation type: move from the periphery to the coordinate point. */Public static final int OUTSIDE_TO_LOCATION = 1;/** displacement animation type: move from coordinate point to peripheral. */Public static final int LOCATION_TO_OUTSIDE = 2;/** displacement animation type: move from the center to the coordinate point. */Public static final int CENTER_TO_LOCATION = 3;/** displacement animation type: move from coordinate point to center point. */Public static final int LOCATION_TO_CENTER = 4; public static final long ANIM_DURATION = 800l; public static final int MAX = 10; public static final int TEXT_SIZE_MAX = 25; public static final int TEXT_SIZE_MIN = 15; private OnClickListener itemClickListener; private static Interpolator interpolator; private static AlphaAnimation animAlpha2Opaque; private static AlphaAnimation animAlpha2Transparent; priv Ate static ScaleAnimation animScaleLarge2Normal, animScaleNormal2Large, animScaleZero2Normal, animScaleNormal2Zero;/** stores the displayed keywords. */Private Vector <String> vecKeywords; private int width, height;/*** the value is true in go2Show (), which identifies a developer to trigger the start animation display. <Br/> * This identifier prevents the animation from being started in advance after the width and height are obtained during keywrods filling. <Br/> * in the show () method, the value is false. <Br/> * Another necessary condition for animation display: the width and height are not 0. <Br/> */private boolean enableShow; private Random random; /*** @ see ANIMATION_IN * @ see ANIMATION_OUT * @ see OUTSIDE_TO_LOCATION * @ see Region * @ see LOCATION_TO_CENTER * @ see CENTER_TO_LOCATION **/private int txtAnimInType, txtAnimOutType; /** the last time the animation was started. */Private long lastStartAnimationTime;/** animation running time. */Private long animDuration; public KeywordsFlow (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); init ();} public KeywordsFlow (Context context, attributeSet attrs) {super (context, attrs); init ();} public KeywordsFlow (Context context) {super (context); init ();} private void init () {lastStartAnimationTime = 0l; animDuration = ANIM_DURATION; random = new Random (); vecKeywords = New Vector <String> (MAX); getViewTreeObserver (). addOnGlobalLayoutListener (this); interpolator = AnimationUtils. loadInterpolator (getContext (), android. r. anim. updated); animAlpha2Opaque = new AlphaAnimation (0.0f, 1.0f); animAlpha2Transparent = new AlphaAnimation (1.0f, 0.0f); Updated = new ScaleAnimation (2, 1, 2, 1 ); animScaleNormal2Large = new ScaleAnimation (1, 2, 1, 2); anim ScaleZero2Normal = new ScaleAnimation (0, 1, 0, 1); animScaleNormal2Zero = new ScaleAnimation (1, 0, 1, 0);} public long getDuration () {return animDuration ;} public void setDuration (long duration) {animDuration = duration;} public boolean feedKeyword (String keyword) {boolean result = false; if (vecKeywords. size () <MAX) {result = vecKeywords. add (keyword) ;}return result ;}/ *** start animation display. <Br/> * the existing TextView will display the exit animation. <Br/> ** @ return: returns true if the animation is displayed normally; otherwise, false. The reason for returning false is as follows: <br/> * 1. The time is not allowed and is restricted by lastStartAnimationTime. <br/> * 2. The width and height values are not obtained. <Br/> */public boolean go2Show (int animType) {if (System. currentTimeMillis ()-Timeout> animDuration) {enableShow = true; if (animType = ANIMATION_IN) {txtAnimInType = Hangzhou; region = LOCATION_TO_CENTER;} else if (animType = ANIMATION_OUT) {txtAnimInType = CENTER_TO_LOCATION; txtAnimOutType = LOCATION_TO_OUTSIDE;} disapper (); boolean result = show (); return result;} Return false;} private void disapper () {int size = getChildCount (); for (int I = size-1; I> = 0; I --) {final TextView txt = (TextView) getChildAt (I); if (txt. getVisibility () = View. GONE) {removeView (txt); continue;} FrameLayout. layoutParams layParams = (LayoutParams) txt. getLayoutParams (); // Log. d ("ANDROID_LAB", txt. getText () + "leftM =" + // layParams. leftMargin + "topM =" + layParams. topMargin // + "Width =" + txt. getWidth (); int [] xy = new int [] {layParams. leftMargin, layParams. topMargin, txt. getWidth ()}; AnimationSet animSet = getAnimationSet (xy, (width> 1), (height> 1), txtAnimOutType); txt. startAnimation (animSet); animSet. setAnimationListener (new AnimationListener () {public void onAnimationStart (Animation animation) {} public void onAnimationRepeat (Animation animation) {} public void onA NimationEnd (Animation animation) {txt. setOnClickListener (null); txt. setClickable (false); txt. setVisibility (View. GONE) ;}}) ;}} private boolean show () {if (width> 0 & height> 0 & vecKeywords! = Null & vecKeywords. size ()> 0 & enableShow) {enableShow = false; lastStartAnimationTime = System. currentTimeMillis (); int xCenter = width> 1, yCenter = height> 1; int size = vecKeywords. size (); int xItem = width/size, yItem = height/size; // Log. d ("ANDROID_LAB ", "-------------------------- width =" + width + // "height =" + height + "xItem =" + xItem // + "yItem =" + yItem + "-------------------- ------- "); Sorted list <Integer> listX = new sorted list <Integer> (), listY = new sorted list <Integer> (); for (int I = 0; I <size; I ++) {// prepare the number of random candidates, corresponding to the x/y axis position listX. add (I * xItem); listY. add (I * yItem + (yItem> 2);} // TextView [] txtArr = new TextView [size]; pipeline list <TextView> listTxtTop = new pipeline list <TextView> (); pipeline list <TextView> listTxtBottom = new pipeline list <TextView> (); for (int I = 0; I <siz E; I ++) {String keyword = vecKeywords. get (I); // random color int ranColor = 0xff000000 | random. nextInt (0x0077ffff); // random position, rough int xy [] = randomXY (random, listX, listY, xItem); // random font size int txtSize = TEXT_SIZE_MIN + random. nextInt (TEXT_SIZE_MAX-TEXT_SIZE_MIN + 1); // instantiate TextViewfinal TextView txt = new TextView (getContext (); txt. setOnClickListener (itemClickListener); txt. setText (keyword); txt. setTextColor (ranC Olor); txt. setTextSize (TypedValue. COMPLEX_UNIT_SP, txtSize); txt. setShadowLayer (2, 2, 2, 0xff696969); txt. setGravity (Gravity. CENTER); // obtain the text length. getPaint (); int strWidth = (int) Math. ceil (paint. measureText (keyword); xy [IDX_TXT_LENGTH] = strWidth; // The first correction: modifies the x coordinate if (xy [IDX_X] + strWidth> width-(xItem> 1 )) {int baseX = width-strWidth; // reduce the probability that the right edge of the text is the same as that of xy [IDX_X] = baseX-xItem + random. NextInt (xItem> 1);} else if (xy [IDX_X] = 0) {// reduces the probability that the left edge of the text is the same as that of xy [IDX_X] = Math. max (random. nextInt (xItem), xItem/3);} xy [IDX_DIS_Y] = Math. abs (xy [IDX_Y]-yCenter); txt. setTag (xy); if (xy [IDX_Y]> yCenter) {listTxtBottom. add (txt);} else {listTxtTop. add (txt) ;}} attach2Screen (listTxtTop, xCenter, yCenter, yItem); attach2Screen (listTxtBottom, xCenter, yCenter, yItem); return true;} return false ;} /** modify Tex Add the Y coordinate of tView to the container. */Private void attach2Screen (optional list <TextView> listTxt, int xCenter, int yCenter, int yItem) {int size = listTxt. size (); sortXYList (listTxt, size); for (int I = 0; I <size; I ++) {TextView txt = listTxt. get (I); int [] iXY = (int []) txt. getTag (); // Log. d ("ANDROID_LAB", "fix [" + txt. getText () + "] x:" + // iXY [IDX_X] + "y:" + iXY [IDX_Y] + "r2 =" // + iXY [IDX_DIS_Y]); // second correction: Corrected y coordinate int yDistance = iXY [IDX_Y]-yCenter; // For the closest to the central point, the value is not greater than yItem <br/> // for those that can be dropped to the central point all the way, the value is also the size to be adjusted <br/> int yMove = Math. abs (yDistance); inner: for (int k = I-1; k> = 0; k --) {int [] kXY = (int []) listTxt. get (k ). getTag (); int startX = kXY [IDX_X]; int endX = startX + kXY [IDX_TXT_LENGTH]; // the Y axis uses the center point as the separation line, if (yDistance * (kXY [IDX_Y]-yCenter)> 0) on the same side {// Log. d ("ANDROID_LAB", "compare:" + // listTxt. get (k ). getText (); if (isXMixe D (startX, endX, iXY [IDX_X], iXY [IDX_X] + iXY [IDX_TXT_LENGTH]) {int tmpMove = Math. abs (iXY [IDX_Y]-kXY [IDX_Y]); if (tmpMove> yItem) {yMove = tmpMove;} else if (yMove> 0) {// cancel the default value. YMove = 0;} // Log. d ("ANDROID_LAB", "break"); break inner ;}}// Log. d ("ANDROID_LAB", txt. getText () + "yMove =" + yMove); if (yMove> yItem) {int maxMove = yMove-yItem; int randomMove = random. nextInt (maxMove); int realMove = Math. max (randomMove, maxMove> 1) * yDistance/Math. abs (yDistance); iXY [IDX_Y] = iXY [IDX_Y]-realMove; iXY [IDX_DIS_Y] = Math. abs (iXY [IDX_Y]-yCenter); // You must sort sortXYList (ListTxt, I + 1);} FrameLayout. layoutParams layParams = new FrameLayout. layoutParams (FrameLayout. layoutParams. WRAP_CONTENT, FrameLayout. layoutParams. WRAP_CONTENT); layParams. gravity = Gravity. LEFT | Gravity. TOP; layParams. leftMargin = iXY [IDX_X]; layParams. topMargin = iXY [IDX_Y]; addView (txt, layParams); // animation AnimationSet animSet = getAnimationSet (iXY, xCenter, yCenter, txtAnimInType); txt. startAnimation (ImSet) ;}} public AnimationSet getAnimationSet (int [] xy, int xCenter, int yCenter, int type) {AnimationSet animSet = new AnimationSet (true); animSet. setInterpolator (interpolator); if (type = OUTSIDE_TO_LOCATION) {animSet. addAnimation (animAlpha2Opaque); animSet. addAnimation (animScaleLarge2Normal); TranslateAnimation translate = new TranslateAnimation (xy [IDX_X] + (xy [IDX_TXT_LENGTH]> 1)-xCenter) <1, 0, (xy [IDX_Y]-yCenter) <1, 0); animSet. addAnimation (translate);} else if (type = LOCATION_TO_OUTSIDE) {animSet. addAnimation (animAlpha2Transparent); animSet. addAnimation (animScaleNormal2Large); TranslateAnimation translate = new TranslateAnimation (0, (xy [IDX_X] + (xy [IDX_TXT_LENGTH]> 1)-xCenter) <1, 0, (xy [IDX_Y]-yCenter) <1); animSet. addAnimation (translate);} else if (type = LOCATION_TO _ CENTER) {animSet. addAnimation (animAlpha2Transparent); animSet. addAnimation (animScaleNormal2Zero); TranslateAnimation translate = new TranslateAnimation (0, (-xy [IDX_X] + xCenter), 0, (-xy [IDX_Y] + yCenter); animSet. addAnimation (translate);} else if (type = CENTER_TO_LOCATION) {animSet. addAnimation (animAlpha2Opaque); animSet. addAnimation (animScaleZero2Normal); TranslateAnimation translate = new Translat EAnimation (-xy [IDX_X] + xCenter), 0, (-xy [IDX_Y] + yCenter), 0); animSet. addAnimation (translate);} animSet. setDuration (animDuration); return animSet;}/*** Bubble Sorting is performed based on the distance from the center to the far. ** @ Param endIdx * start position. * @ Param txtArr * array to be sorted. **/Private void sortXYList (comment list <TextView> listTxt, int endIdx) {for (int I = 0; I <endIdx; I ++) {for (int k = I + 1; k <endIdx; k ++) {if (int []) listTxt. get (k ). getTag () [IDX_DIS_Y] <(int []) listTxt. get (I ). getTag () [IDX_DIS_Y]) {TextView iTmp = listTxt. get (I); TextView kTmp = listTxt. get (k); listTxt. set (I, kTmp); listTxt. set (k, iTmp) ;}}}/** whether the line represented by line A and line B has an intersection in the x-axis ing. */Private boolean isXMixed (int startA, int endA, int startB, int endB) {boolean result = false; if (startB> = startA & startB <= endA) {result = true;} else if (endB >=starta & endB <= endA) {result = true;} else if (startA >=startb & startA <= endB) {result = true;} else if (endA> = startB & endA <= endB) {result = true;} return result;} private int [] randomXY (Random ran, revoke list <Integer> l IstX, sorted list <Integer> listY, int xItem) {int [] arr = new int [4]; arr [IDX_X] = listX. remove (ran. nextInt (listX. size (); arr [IDX_Y] = listY. remove (ran. nextInt (listY. size (); return arr;} public void onGlobalLayout () {int tmpW = getWidth (); int tmpH = getHeight (); if (width! = TmpW | height! = TmpH) {width = tmpW; height = tmpH; show () ;}} public Vector <String> getKeywords () {return vecKeywords;} public void rubKeywords () {vecKeywords. clear ();}/** clear all textviews directly. The animation is not displayed until it is cleared. */Public void rubAllViews () {removeAllViews ();} public void setOnClickListener (OnClickListener listener) {itemClickListener = listener ;}}