自定义编辑框 + 搜索页面无序排列

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:background="@drawable/bg_search" >
 6 
 7     <LinearLayout
 8         android:id="@+id/search_layout"
 9         android:layout_width="match_parent"
10         android:layout_height="wrap_content"
11         android:layout_alignParentLeft="true"
12         android:layout_alignParentTop="true"
13         android:layout_marginLeft="25dp"
14         android:layout_marginRight="25dp"
15         android:layout_marginTop="30dp"
16         android:orientation="vertical" >
17 
18         <com.wxcily.xunbo2.DeletableEditText
19             android:id="@+id/search_view"
20             android:layout_width="match_parent"
21             android:layout_height="wrap_content"
22             android:background="@drawable/bg_edittext"
23             android:drawableLeft="@drawable/ic_edittext_search"
24             android:drawablePadding="6dp"
25             android:drawableRight="@drawable/ic_edittext_delete"
26             android:hint="请输入您要搜索的影片..."
27             android:paddingBottom="7dp"
28             android:paddingLeft="9dp"
29             android:paddingRight="8dp"
30             android:paddingTop="7dp"
31             android:singleLine="true"
32             android:textColor="#ffffff"
33             android:textCursorDrawable="@null"
34             android:textSize="16dp" />
35 
36         <LinearLayout
37             android:layout_width="wrap_content"
38             android:layout_height="wrap_content"
39             android:layout_marginTop="10dp"
40             android:orientation="horizontal" >
41 
42             <Button
43                 android:id="@+id/search_button"
44                 android:layout_width="match_parent"
45                 android:layout_height="33dp"
46                 android:background="@drawable/bg_button_green"
47                 android:drawableLeft="@drawable/ic_button_search"
48                 android:drawablePadding="5dp"
49                 android:paddingLeft="20dp"
50                 android:paddingRight="20dp"
51                 android:text="云搜索"
52                 android:textColor="#ffffff"
53                 android:textSize="16dp" />
54 
55             <Button
56                 android:id="@+id/app_button"
57                 android:layout_width="match_parent"
58                 android:layout_height="33dp"
59                 android:layout_marginLeft="10dp"
60                 android:background="@drawable/bg_button_red"
61                 android:drawableLeft="@drawable/ic_button_star"
62                 android:drawablePadding="5dp"
63                 android:paddingLeft="15dp"
64                 android:paddingRight="15dp"
65                 android:text="精品应用"
66                 android:textColor="#ffffff"
67                 android:textSize="16dp" />
68         </LinearLayout>
69     </LinearLayout>
70 
71     <com.wxcily.xunbo2.KeywordsFlow
72         android:id="@+id/keywordsflow"
73         android:layout_width="match_parent"
74         android:layout_height="match_parent"
75         android:layout_below="@+id/search_layout" />
76 
77     <ImageView
78         android:id="@+id/back_arrow"
79         android:layout_width="wrap_content"
80         android:layout_height="wrap_content"
81         android:layout_alignParentBottom="true"
82         android:layout_centerHorizontal="true"
83         android:layout_marginBottom="14dp"
84         android:src="@drawable/ic_back_arrow" />
85 
86 </RelativeLayout>
 1 <!-- bg_button_green.xml -->
 2 <?xml version="1.0" encoding="utf-8"?>
 3 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 5     <item android:state_pressed="true"><shape>
 6             <solid android:color="#24a042" />
 7             <corners android:radius="3dip" />
 8         </shape></item>
 9     <item><shape>
10             <solid android:color="#4cc05f" />
11             <corners android:radius="3dip" />
12         </shape></item>
13 </selector>
<!-- bg_button_red.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"><shape>
            <solid android:color="#a34337" />
            <corners android:radius="3dip" />
        </shape></item>
    <item><shape>
            <solid android:color="#cc4238" />
            <corners android:radius="3dip" />
        </shape></item>
</selector>

 

  1 import android.content.Context;
  2 import android.graphics.drawable.Drawable;
  3 import android.text.Editable;
  4 import android.text.TextWatcher;
  5 import android.util.AttributeSet;
  6 import android.view.MotionEvent;
  7 import android.view.View;
  8 import android.view.animation.Animation;
  9 import android.view.animation.CycleInterpolator;
 10 import android.view.animation.TranslateAnimation;
 11 import android.widget.EditText;
 12 
 13 // 自定义控件
 14 public class DeletableEditText extends EditText {
 15     private Drawable mRightDrawable;
 16     private boolean isHasFocus;
 17 
 18     public DeletableEditText(Context context) {
 19         super(context);
 20         init();
 21     }
 22 
 23     public DeletableEditText(Context context, AttributeSet attrs) {
 24         super(context, attrs);
 25         init();
 26     }
 27 
 28     public DeletableEditText(Context context, AttributeSet attrs, int defStyle) {
 29         super(context, attrs, defStyle);
 30         init();
 31     }
 32 
 33     private void init() {
 34         // getCompoundDrawables:
 35         // Returns drawables for the left, top, right, and bottom borders.
 36         Drawable[] drawables = this.getCompoundDrawables();
 37 
 38         // 取得right位置的Drawable
 39         // 即我们在布局文件中设置的android:drawableRight
 40         mRightDrawable = drawables[2];
 41 
 42         // 设置焦点变化的监听
 43         this.setOnFocusChangeListener(new FocusChangeListenerImpl());
 44         // 设置EditText文字变化的监听
 45         this.addTextChangedListener(new TextWatcherImpl());
 46         // 初始化时让右边clean图标不可见
 47         setClearDrawableVisible(false);
 48     }
 49 
 50     /**
 51      * 当手指抬起的位置在clean的图标的区域 我们将此视为进行清除操作 getWidth():得到控件的宽度
 52      * event.getX():抬起时的坐标(改坐标是相对于控件本身而言的)
 53      * getTotalPaddingRight():clean的图标左边缘至控件右边缘的距离
 54      * getPaddingRight():clean的图标右边缘至控件右边缘的距离 于是: getWidth() -
 55      * getTotalPaddingRight()表示: 控件左边到clean的图标左边缘的区域 getWidth() -
 56      * getPaddingRight()表示: 控件左边到clean的图标右边缘的区域 所以这两者之间的区域刚好是clean的图标的区域
 57      */
 58     @Override
 59     public boolean onTouchEvent(MotionEvent event) {
 60         switch (event.getAction()) {
 61         case MotionEvent.ACTION_UP:
 62 
 63             boolean isClean = (event.getX() > (getWidth() - getTotalPaddingRight()))
 64                     && (event.getX() < (getWidth() - getPaddingRight()));
 65             if (isClean) {
 66                 setText("");
 67             }
 68             break;
 69 
 70         default:
 71             break;
 72         }
 73         return super.onTouchEvent(event);
 74     }
 75 
 76     private class FocusChangeListenerImpl implements OnFocusChangeListener {
 77         @Override
 78         public void onFocusChange(View v, boolean hasFocus) {
 79             isHasFocus = hasFocus;
 80             if (isHasFocus) {
 81                 boolean isVisible = getText().toString().length() >= 1;
 82                 setClearDrawableVisible(isVisible);
 83             } else {
 84                 setClearDrawableVisible(false);
 85             }
 86         }
 88     }
 89 
 90     // 当输入结束后判断是否显示右边clean的图标
 91     private class TextWatcherImpl implements TextWatcher {
 92         @Override
 93         public void afterTextChanged(Editable s) {
 94             boolean isVisible = getText().toString().length() >= 1;
 95             setClearDrawableVisible(isVisible);
 96         }
 98         @Override
 99         public void beforeTextChanged(CharSequence s, int start, int count,
100                 int after) {
101         }
103         @Override
104         public void onTextChanged(CharSequence s, int start, int before,
105                 int count) {
106         }
108     }
109 
110     // 隐藏或者显示右边clean的图标
111     protected void setClearDrawableVisible(boolean isVisible) {
112         Drawable rightDrawable;
113         if (isVisible) {
114             rightDrawable = mRightDrawable;
115         } else {
116             rightDrawable = null;
117         }
118         // 使用代码设置该控件left, top, right, and bottom处的图标
119         setCompoundDrawables(getCompoundDrawables()[0],
120                 getCompoundDrawables()[1], rightDrawable,
121                 getCompoundDrawables()[3]);
122     }
123 
124     // 显示一个动画,以提示用户输入
125     public void setShakeAnimation() {
126         this.startAnimation(shakeAnimation(5));
128     }
129 
130     // CycleTimes动画重复的次数
131     public Animation shakeAnimation(int CycleTimes) {
132         Animation translateAnimation = new TranslateAnimation(0, 10, 0, 10);
133         translateAnimation.setInterpolator(new CycleInterpolator(CycleTimes));
134         translateAnimation.setDuration(1000);
135         return translateAnimation;
136     }
137 }

 

import java.util.Random;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener {
    private static final int FEEDKEY_START = 1;
    private ImageView back_arrow;
    private Animation shakeAnim;
    private DeletableEditText searchEdit;
    private KeywordsFlow keywordsFlow;
    private int STATE = 1;

    private static String[] keywords = new String[] { "娘要嫁人", "球爱酒吧", "使徒行者",
            "亮剑", "完美搭档", "致青春", "非常完美", "一生一世", "穿越火线", "天龙八部", "匹诺曹", "让子弹飞",
            "穿越火线", "情定三生", "心术", "马向阳下乡记", "人在囧途", " 高达", " 刀剑神域", "泡芙小姐",
            "尖刀出鞘", "甄嬛传", "兵出潼关", "电锯惊魂3D", "古剑奇谭", "同桌的你" };

    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case FEEDKEY_START:
                keywordsFlow.rubKeywords();
                feedKeywordsFlow(keywordsFlow, keywords);
                keywordsFlow.go2Show(KeywordsFlow.ANIMATION_OUT);
                sendEmptyMessageDelayed(FEEDKEY_START, 5000);
                break;
            }
        };
    };

    private static 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);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        shakeAnim = AnimationUtils.loadAnimation(this, R.anim.shake_y);
        initView();
    }

    private void initView() {
        keywordsFlow = (KeywordsFlow) findViewById(R.id.keywordsflow);
        keywordsFlow.setDuration(1000l);
        keywordsFlow.setOnItemClickListener(this);
        back_arrow = (ImageView) findViewById(R.id.back_arrow);
        back_arrow.setAnimation(shakeAnim);
        searchEdit = (DeletableEditText) findViewById(R.id.search_view);
        feedKeywordsFlow(keywordsFlow, keywords);
        keywordsFlow.go2Show(KeywordsFlow.ANIMATION_IN);
        handler.sendEmptyMessageDelayed(FEEDKEY_START, 5000);
    }

    @Override
    public void onClick(View v) {
        if (v instanceof TextView) {
            String keyword = ((TextView) v).getText().toString().trim();
            searchEdit.setText(keyword);
            searchEdit.setSelection(keyword.length());
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        back_arrow.clearAnimation();
        handler.removeMessages(FEEDKEY_START);
        STATE = 0;
    }

    @Override
    protected void onStop() {
        super.onStop();
        handler.removeMessages(FEEDKEY_START);
        STATE = 0;
    }

    @Override
    public void onPause() {
        super.onPause();
        handler.removeMessages(FEEDKEY_START);
        STATE = 0;
    }

    @Override
    public void onResume() {
        super.onResume();
        if (STATE == 0) {
            keywordsFlow.rubKeywords();
            handler.sendEmptyMessageDelayed(FEEDKEY_START, 3000);
        }

    }
}

 

  1 import java.util.LinkedList;
  2 import java.util.Random;
  3 import java.util.Vector;
  4 import android.content.Context;
  5 import android.graphics.Color;
  6 import android.graphics.Paint;
  7 import android.util.AttributeSet;
  8 import android.util.Log;
  9 import android.util.TypedValue;
 10 import android.view.Gravity;
 11 import android.view.View;
 12 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 13 import android.view.animation.AlphaAnimation;
 14 import android.view.animation.Animation;
 15 import android.view.animation.Animation.AnimationListener;
 16 import android.view.animation.AnimationSet;
 17 import android.view.animation.AnimationUtils;
 18 import android.view.animation.Interpolator;
 19 import android.view.animation.ScaleAnimation;
 20 import android.view.animation.TranslateAnimation;
 21 import android.widget.FrameLayout;
 22 import android.widget.TextView;
 23 
 24 public class KeywordsFlow extends FrameLayout implements OnGlobalLayoutListener {
 25     public static final int IDX_X = 0;
 26     public static final int IDX_Y = 1;
 27     public static final int IDX_TXT_LENGTH = 2;
 28     public static final int IDX_DIS_Y = 3;
 29     /** 由外至内的动画。 */
 30     public static final int ANIMATION_IN = 1;
 31     /** 由内至外的动画。 */
 32     public static final int ANIMATION_OUT = 2;
 33     /** 位移动画类型:从外围移动到坐标点。 */
 34     public static final int OUTSIDE_TO_LOCATION = 1;
 35     /** 位移动画类型:从坐标点移动到外围。 */
 36     public static final int LOCATION_TO_OUTSIDE = 2;
 37     /** 位移动画类型:从中心点移动到坐标点。 */
 38     public static final int CENTER_TO_LOCATION = 3;
 39     /** 位移动画类型:从坐标点移动到中心点。 */
 40     public static final int LOCATION_TO_CENTER = 4;
 41     public static final long ANIM_DURATION = 800l;
 42     public static final int MAX = 10;
 43     public static final int TEXT_SIZE_MAX = 21;
 44     public static final int TEXT_SIZE_MIN = 14;
 45     private OnClickListener itemClickListener;
 46     private static Interpolator interpolator;
 47     private static AlphaAnimation animAlpha2Opaque;
 48     private static AlphaAnimation animAlpha2Transparent;
 49     private static ScaleAnimation animScaleLarge2Normal, animScaleNormal2Large,
 50             animScaleZero2Normal, animScaleNormal2Zero;
 51     /** 存储显示的关键字。 */
 52     private Vector<String> vecKeywords;
 53     private int width, height;
 54     /**
 55      * go2Show()中被赋值为true,标识开发人员触发其开始动画显示。<br/>
 56      * 本标识的作用是防止在填充keywrods未完成的过程中获取到width和height后提前启动动画。<br/>
 57      * 在show()方法中其被赋值为false。<br/>
 58      * 真正能够动画显示的另一必要条件:width 和 height不为0。<br/>
 59      */
 60     private boolean enableShow;
 61     private Random random;
 62     /**
 63      * @see ANIMATION_IN
 64      * @see ANIMATION_OUT
 65      * @see OUTSIDE_TO_LOCATION
 66      * @see LOCATION_TO_OUTSIDE
 67      * @see LOCATION_TO_CENTER
 68      * @see CENTER_TO_LOCATION
 69      * */
 70     private int txtAnimInType, txtAnimOutType;
 71     /** 最近一次启动动画显示的时间。 */
 72     private long lastStartAnimationTime;
 73     /** 动画运行时间。 */
 74     private long animDuration;
 75 
 76     public KeywordsFlow(Context context, AttributeSet attrs, int defStyle) {
 77         super(context, attrs, defStyle);
 78         init();
 79     }
 80 
 81     public KeywordsFlow(Context context, AttributeSet attrs) {
 82         super(context, attrs);
 83         init();
 84     }
 85 
 86     public KeywordsFlow(Context context) {
 87         super(context);
 88         init();
 89     }
 90 
 91     private void init() {
 92         lastStartAnimationTime = 0l;
 93         animDuration = ANIM_DURATION;
 94         random = new Random();
 95         vecKeywords = new Vector<String>(MAX);
 96         getViewTreeObserver().addOnGlobalLayoutListener(this);
 97         interpolator = AnimationUtils.loadInterpolator(getContext(),
 98                 android.R.anim.decelerate_interpolator);
 99         animAlpha2Opaque = new AlphaAnimation(0.0f, 1.0f);
100         animAlpha2Transparent = new AlphaAnimation(1.0f, 0.0f);
101         animScaleLarge2Normal = new ScaleAnimation(2, 1, 2, 1);
102         animScaleNormal2Large = new ScaleAnimation(1, 2, 1, 2);
103         animScaleZero2Normal = new ScaleAnimation(0, 1, 0, 1);
104         animScaleNormal2Zero = new ScaleAnimation(1, 0, 1, 0);
105     }
106 
107     public long getDuration() {
108         return animDuration;
109     }
110 
111     public void setDuration(long duration) {
112         animDuration = duration;
113     }
114 
115     public boolean feedKeyword(String keyword) {
116         boolean result = false;
117         if (vecKeywords.size() < MAX) {
118             result = vecKeywords.add(keyword);
119         }
120         return result;
121     }
122 
123     /**
124      * 开始动画显示。<br/>
125      * 之前已经存在的TextView将会显示退出动画。<br/>
126      * 
127      * @return 正常显示动画返回true;反之为false。返回false原因如下:<br/>
128      *         1.时间上不允许,受lastStartAnimationTime的制约;<br/>
129      *         2.未获取到width和height的值。<br/>
130      */
131     public boolean go2Show(int animType) {
132         if (System.currentTimeMillis() - lastStartAnimationTime > animDuration) {
133             enableShow = true;
134             if (animType == ANIMATION_IN) {
135                 txtAnimInType = OUTSIDE_TO_LOCATION;
136                 txtAnimOutType = LOCATION_TO_CENTER;
137             } else if (animType == ANIMATION_OUT) {
138                 txtAnimInType = CENTER_TO_LOCATION;
139                 txtAnimOutType = LOCATION_TO_OUTSIDE;
140             }
141             disapper();
142             boolean result = show();
143             return result;
144         }
145         return false;
146     }
147 
148     private void disapper() {
149         int size = getChildCount();
150         for (int i = size - 1; i >= 0; i--) {
151             final TextView txt = (TextView) getChildAt(i);
152             if (txt.getVisibility() == View.GONE) {
153                 removeView(txt);
154                 continue;
155             }
156             FrameLayout.LayoutParams layParams = (LayoutParams) txt
157                     .getLayoutParams();
158             // Log.d("ANDROID_LAB", txt.getText() + " leftM=" +
159             // layParams.leftMargin + " topM=" + layParams.topMargin
160             // + " width=" + txt.getWidth());
161             int[] xy = new int[] { layParams.leftMargin, layParams.topMargin,
162                     txt.getWidth() };
163             AnimationSet animSet = getAnimationSet(xy, (width >> 1),
164                     (height >> 1), txtAnimOutType);
165             txt.startAnimation(animSet);
166             animSet.setAnimationListener(new AnimationListener() {
167                 public void onAnimationStart(Animation animation) {
168                 }
169 
170                 public void onAnimationRepeat(Animation animation) {
171                 }
172 
173                 public void onAnimationEnd(Animation animation) {
174                     txt.setOnClickListener(null);
175                     txt.setClickable(false);
176                     txt.setVisibility(View.GONE);
177                 }
178             });
179         }
180     }
181 
182     private boolean show() {
183         if (width > 0 && height > 0 && vecKeywords != null
184                 && vecKeywords.size() > 0 && enableShow) {
185             enableShow = false;
186             lastStartAnimationTime = System.currentTimeMillis();
187             // 找到中心点
188             int xCenter = width >> 1, yCenter = height >> 1;
189             // 关键字的个数。
190             int size = vecKeywords.size();
191             int xItem = width / size, yItem = height / size;
192             Log.d("ANDROID_LAB", "--------------------------width=" + width
193                     + " height=" + height + "  xItem=" + xItem + " yItem="
194                     + yItem + "---------------------------");
195             LinkedList<Integer> listX = new LinkedList<Integer>(), listY = new LinkedList<Integer>();
196             for (int i = 0; i < size; i++) {
197                 // 准备随机候选数,分别对应x/y轴位置
198                 listX.add(i * xItem);
199                 listY.add(i * yItem + (yItem >> 2));
200                 Log.e("Search", "ListX:" + (i * xItem) + "#listY:"
201                         + (i * yItem + (yItem >> 2)));
202             }
203             // TextView[] txtArr = new TextView[size];
204             LinkedList<TextView> listTxtTop = new LinkedList<TextView>();
205             LinkedList<TextView> listTxtBottom = new LinkedList<TextView>();
206             for (int i = 0; i < size; i++) {
207                 String keyword = vecKeywords.get(i);
208                 // 随机颜色
209                 // int ranColor = 0xff000000 | random.nextInt(0x0077ffff);
210                 // 随机位置,糙值
211                 int xy[] = randomXY(random, listX, listY, xItem);
212                 // 随机字体大小
213                 int txtSize = TEXT_SIZE_MIN
214                         + random.nextInt(TEXT_SIZE_MAX - TEXT_SIZE_MIN + 1);
215                 // 实例化TextView
216                 final TextView txt = new TextView(getContext());
217                 txt.setOnClickListener(itemClickListener);
218                 txt.setText(keyword);
219                 txt.setTextColor(Color.parseColor("#8cffffff"));
220                 txt.setTextSize(TypedValue.COMPLEX_UNIT_SP, txtSize);
221                 txt.setShadowLayer(1, 1, 1, 0xdd696969);
222                 txt.setGravity(Gravity.CENTER);
223 
224                 // txt.setBackgroundColor(Color.RED);
225                 // 获取文本长度
226                 Paint paint = txt.getPaint();
227                 int strWidth = (int) Math.ceil(paint.measureText(keyword));
228                 xy[IDX_TXT_LENGTH] = strWidth;
229                 // 第一次修正:修正x坐标
230                 if (xy[IDX_X] + strWidth > width - (xItem >> 1)) {
231                     int baseX = width - strWidth;
232                     // 减少文本右边缘一样的概率
233                     xy[IDX_X] = baseX - xItem + random.nextInt(xItem >> 1);
234                 } else if (xy[IDX_X] == 0) {
235                     // 减少文本左边缘一样的概率
236                     xy[IDX_X] = Math.max(random.nextInt(xItem), xItem / 3);
237                 }
238                 xy[IDX_DIS_Y] = Math.abs(xy[IDX_Y] - yCenter);
239                 txt.setTag(xy);
240                 if (xy[IDX_Y] > yCenter) {
241                     listTxtBottom.add(txt);
242                 } else {
243                     listTxtTop.add(txt);
244                 }
245             }
246             attach2Screen(listTxtTop, xCenter, yCenter, yItem);
247             attach2Screen(listTxtBottom, xCenter, yCenter, yItem);
248             return true;
249         }
250         return false;
251     }
252 
253     /** 修正TextView的Y坐标将将其添加到容器上。 */
254     private void attach2Screen(LinkedList<TextView> listTxt, int xCenter,
255             int yCenter, int yItem) {
256         int size = listTxt.size();
257         sortXYList(listTxt, size);
258         for (int i = 0; i < size; i++) {
259             TextView txt = listTxt.get(i);
260             int[] iXY = (int[]) txt.getTag();
261             // Log.d("ANDROID_LAB", "fix[  " + txt.getText() + "  ] x:" +
262             // iXY[IDX_X] + " y:" + iXY[IDX_Y] + " r2="
263             // + iXY[IDX_DIS_Y]);
264             // 第二次修正:修正y坐标
265             int yDistance = iXY[IDX_Y] - yCenter;
266             // 对于最靠近中心点的,其值不会大于yItem<br/>
267             // 对于可以一路下降到中心点的,则该值也是其应调整的大小<br/>
268             int yMove = Math.abs(yDistance);
269             inner: for (int k = i - 1; k >= 0; k--) {
270                 int[] kXY = (int[]) listTxt.get(k).getTag();
271                 int startX = kXY[IDX_X];
272                 int endX = startX + kXY[IDX_TXT_LENGTH];
273                 // y轴以中心点为分隔线,在同一侧
274                 if (yDistance * (kXY[IDX_Y] - yCenter) > 0) {
275                     // Log.d("ANDROID_LAB", "compare:" +
276                     // listTxt.get(k).getText());
277                     if (isXMixed(startX, endX, iXY[IDX_X], iXY[IDX_X]
278                             + iXY[IDX_TXT_LENGTH])) {
279                         int tmpMove = Math.abs(iXY[IDX_Y] - kXY[IDX_Y]);
280                         if (tmpMove > yItem) {
281                             yMove = tmpMove;
282                         } else if (yMove > 0) {
283                             // 取消默认值。
284                             yMove = 0;
285                         }
286                         // Log.d("ANDROID_LAB", "break");
287                         break inner;
288                     }
289                 }
290             }
291             // Log.d("ANDROID_LAB", txt.getText() + " yMove=" + yMove);
292             if (yMove > yItem) {
293                 int maxMove = yMove - yItem;
294                 int randomMove = random.nextInt(maxMove);
295                 int realMove = Math.max(randomMove, maxMove >> 1) * yDistance
296                         / Math.abs(yDistance);
297                 iXY[IDX_Y] = iXY[IDX_Y] - realMove;
298                 iXY[IDX_DIS_Y] = Math.abs(iXY[IDX_Y] - yCenter);
299                 // 已经调整过前i个需要再次排序
300                 sortXYList(listTxt, i + 1);
301             }
302             FrameLayout.LayoutParams layParams = new FrameLayout.LayoutParams(
303                     FrameLayout.LayoutParams.WRAP_CONTENT,
304                     FrameLayout.LayoutParams.WRAP_CONTENT);
305             layParams.gravity = Gravity.LEFT | Gravity.TOP;
306             layParams.leftMargin = iXY[IDX_X];
307             layParams.topMargin = iXY[IDX_Y];
308             addView(txt, layParams);
309             // 动画
310             AnimationSet animSet = getAnimationSet(iXY, xCenter, yCenter,
311                     txtAnimInType);
312             txt.startAnimation(animSet);
313         }
314     }
315 
316     public AnimationSet getAnimationSet(int[] xy, int xCenter, int yCenter,
317             int type) {
318         AnimationSet animSet = new AnimationSet(true);
319         animSet.setInterpolator(interpolator);
320         if (type == OUTSIDE_TO_LOCATION) {
321             animSet.addAnimation(animAlpha2Opaque);
322             animSet.addAnimation(animScaleLarge2Normal);
323             TranslateAnimation translate = new TranslateAnimation((xy[IDX_X]
324                     + (xy[IDX_TXT_LENGTH] >> 1) - xCenter) << 1, 0,
325                     (xy[IDX_Y] - yCenter) << 1, 0);
326             animSet.addAnimation(translate);
327         } else if (type == LOCATION_TO_OUTSIDE) {
328             animSet.addAnimation(animAlpha2Transparent);
329             animSet.addAnimation(animScaleNormal2Large);
330             TranslateAnimation translate = new TranslateAnimation(0, (xy[IDX_X]
331                     + (xy[IDX_TXT_LENGTH] >> 1) - xCenter) << 1, 0,
332                     (xy[IDX_Y] - yCenter) << 1);
333             animSet.addAnimation(translate);
334         } else if (type == LOCATION_TO_CENTER) {
335             animSet.addAnimation(animAlpha2Transparent);
336             animSet.addAnimation(animScaleNormal2Zero);
337             TranslateAnimation translate = new TranslateAnimation(0,
338                     (-xy[IDX_X] + xCenter), 0, (-xy[IDX_Y] + yCenter));
339             animSet.addAnimation(translate);
340         } else if (type == CENTER_TO_LOCATION) {
341             animSet.addAnimation(animAlpha2Opaque);
342             animSet.addAnimation(animScaleZero2Normal);
343             TranslateAnimation translate = new TranslateAnimation(
344                     (-xy[IDX_X] + xCenter), 0, (-xy[IDX_Y] + yCenter), 0);
345             animSet.addAnimation(translate);
346         }
347         animSet.setDuration(animDuration);
348         return animSet;
349     }
350 
351     /**
352      * 根据与中心点的距离由近到远进行冒泡排序。
353      * 
354      * @param endIdx
355      *            起始位置。
356      * @param txtArr
357      *            待排序的数组。
358      * 
359      */
360     private void sortXYList(LinkedList<TextView> listTxt, int endIdx) {
361         for (int i = 0; i < endIdx; i++) {
362             for (int k = i + 1; k < endIdx; k++) {
363                 if (((int[]) listTxt.get(k).getTag())[IDX_DIS_Y] < ((int[]) listTxt
364                         .get(i).getTag())[IDX_DIS_Y]) {
365                     TextView iTmp = listTxt.get(i);
366                     TextView kTmp = listTxt.get(k);
367                     listTxt.set(i, kTmp);
368                     listTxt.set(k, iTmp);
369                 }
370             }
371         }
372     }
373 
374     /** A线段与B线段所代表的直线在X轴映射上是否有交集。 */
375     private boolean isXMixed(int startA, int endA, int startB, int endB) {
376         boolean result = false;
377         if (startB >= startA && startB <= endA) {
378             result = true;
379         } else if (endB >= startA && endB <= endA) {
380             result = true;
381         } else if (startA >= startB && startA <= endB) {
382             result = true;
383         } else if (endA >= startB && endA <= endB) {
384             result = true;
385         }
386         return result;
387     }
388 
389     private int[] randomXY(Random ran, LinkedList<Integer> listX,
390             LinkedList<Integer> listY, int xItem) {
391         int[] arr = new int[4];
392         arr[IDX_X] = listX.remove(ran.nextInt(listX.size()));
393         arr[IDX_Y] = listY.remove(ran.nextInt(listY.size()));
394         return arr;
395     }
396 
397     public void onGlobalLayout() {
398         int tmpW = getWidth();
399         int tmpH = getHeight();
400         if (width != tmpW || height != tmpH) {
401             width = tmpW;
402             height = tmpH;
403             show();
404         }
405     }
406 
407     public Vector<String> getKeywords() {
408         return vecKeywords;
409     }
410 
411     public void rubKeywords() {
412         vecKeywords.clear();
413     }
414 
415     /** 直接清除所有的TextView。在清除之前不会显示动画。 */
416     public void rubAllViews() {
417         removeAllViews();
418     }
419 
420     public void setOnItemClickListener(OnClickListener listener) {
421         itemClickListener = listener;
422     }
431 }

 

转载于:https://www.cnblogs.com/androidsj/p/4224456.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值