###转载请注明出处王亟亟的大牛之路
一直对Animation属于可有可无的不在意,看到个例子,觉得在不切换的情况下,适当的应用还真是蛮好看的。
包结构:

一个类一个控件,内容简单。

运行效果:

下方的下方箭头会上下移动,页面内的所有散乱的文字都是TextView,以及搜索和带删除的EditText

主Activity

public class MainActivity extends Activity implements OnClickListener {private static final int FEEDKEY_START = 1;private ImageView back_arrow;private ImageView search_button;private Animation shakeAnim;private DeletableEditText searchEdit;private KeywordsFlow keywordsFlow;private int STATE = 1;//页面滚动的数据源private static String[] keywords = new String[] { "弗拉基米尔", "希维尔", "蒙多","茂凯", "潘森", "波比", "拉克丝", "索拉卡", "娑娜", "伊泽瑞尔", "费德提克", " 雷克顿","古拉加斯", "卡萨丁", "迦娜", "奥莉安娜", "嘉文四世", " 莫德凯撒", " 崔丝塔娜", "布兰德","卡尔玛", "塔里克", "莫甘娜", "凯南", " 兰博", "斯维因" ,"卡尔萨斯"};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);}}@Overrideprotected 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);search_button=(ImageView)findViewById(R.id.search_button);search_button.setOnClickListener(this);feedKeywordsFlow(keywordsFlow, keywords);keywordsFlow.go2Show(KeywordsFlow.ANIMATION_IN);handler.sendEmptyMessageDelayed(FEEDKEY_START, 5000);}@Overridepublic void onClick(View v) {if (v instanceof TextView) {String keyword = ((TextView) v).getText().toString().trim();searchEdit.setText(keyword);searchEdit.setSelection(keyword.length());}if(v.getId()==R.id.search_button&&searchEdit.getText().toString().length()!=0){Toast.makeText(MainActivity.this, "你搜索了 "+searchEdit.getText().toString(), Toast.LENGTH_SHORT).show();}}@Overridepublic void onBackPressed() {Intent intent = new Intent(Intent.ACTION_MAIN);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addCategory(Intent.CATEGORY_HOME);startActivity(intent);}@Overrideprotected void onDestroy() {super.onDestroy();back_arrow.clearAnimation();handler.removeMessages(FEEDKEY_START);STATE = 0;}@Overrideprotected void onStop() {super.onStop();handler.removeMessages(FEEDKEY_START);STATE = 0;}@Overridepublic void onPause() {super.onPause();handler.removeMessages(FEEDKEY_START);STATE = 0;}@Overridepublic void onResume() {super.onResume();if (STATE == 0) {keywordsFlow.rubKeywords();handler.sendEmptyMessageDelayed(FEEDKEY_START, 3000);}}
}

####分析:
用handle控制每次动画出现的时间,以及效果排列的算法。
提交按钮之所以不用Button因为 instanceof TextView的时候把Button也算进去了,无法做出分辨(Button 继承于TextView)

布局文件:

<?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:background="@drawable/bg_search" ><LinearLayoutandroid:id="@+id/search_layout"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:layout_marginLeft="25dp"android:layout_marginRight="25dp"android:layout_marginTop="30dp"android:orientation="vertical" ><com.wjj.demo.DeletableEditTextandroid:id="@+id/search_view"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/bg_edittext"android:drawableLeft="@drawable/ic_edittext_search"android:drawablePadding="6dp"android:drawableRight="@drawable/ic_edittext_delete"android:hint="请输入您要搜索的内容..."android:paddingBottom="7dp"android:paddingLeft="9dp"android:paddingRight="8dp"android:paddingTop="7dp"android:singleLine="true"android:textColor="#ffffff"android:textCursorDrawable="@null"android:textSize="16dp" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="3dp"android:orientation="horizontal" ><ImageViewandroid:id="@+id/search_button"android:layout_width="80dp"android:layout_height="40dp"android:src="@drawable/ic_button_search"/></LinearLayout></LinearLayout><com.wjj.demo.KeywordsFlowandroid:id="@+id/keywordsflow"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@+id/search_layout" /><ImageViewandroid:id="@+id/back_arrow"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="14dp"android:src="@drawable/ic_back_arrow" /></RelativeLayout>

自定义EditText

public class DeletableEditText extends EditText{private Drawable mRightDrawable;private boolean isHasFocus;public DeletableEditText(Context context) {super(context);init();}public DeletableEditText(Context context, AttributeSet attrs) {super(context, attrs);init();}public DeletableEditText(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}private void init(){//getCompoundDrawables://Returns drawables for the left, top, right, and bottom borders.Drawable [] drawables=this.getCompoundDrawables();//取得right位置的Drawable//即我们在布局文件中设置的android:drawableRightmRightDrawable=drawables[2];    //设置焦点变化的监听this.setOnFocusChangeListener(new FocusChangeListenerImpl());//设置EditText文字变化的监听this.addTextChangedListener(new TextWatcherImpl());//初始化时让右边clean图标不可见setClearDrawableVisible(false);}/*** 当手指抬起的位置在clean的图标的区域* 我们将此视为进行清除操作* getWidth():得到控件的宽度* event.getX():抬起时的坐标(改坐标是相对于控件本身而言的)* getTotalPaddingRight():clean的图标左边缘至控件右边缘的距离* getPaddingRight():clean的图标右边缘至控件右边缘的距离* 于是:* getWidth() - getTotalPaddingRight()表示:* 控件左边到clean的图标左边缘的区域* getWidth() - getPaddingRight()表示:* 控件左边到clean的图标右边缘的区域* 所以这两者之间的区域刚好是clean的图标的区域*/@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_UP:boolean isClean =(event.getX() > (getWidth() - getTotalPaddingRight()))&&(event.getX() < (getWidth() - getPaddingRight()));if (isClean) {setText("");}break;default:break;}return super.onTouchEvent(event);}private class FocusChangeListenerImpl implements OnFocusChangeListener{@Overridepublic void onFocusChange(View v, boolean hasFocus) {isHasFocus=hasFocus;if (isHasFocus) {boolean isVisible=getText().toString().length()>=1;setClearDrawableVisible(isVisible);} else {setClearDrawableVisible(false);}}}//当输入结束后判断是否显示右边clean的图标private class TextWatcherImpl implements TextWatcher{@Overridepublic void afterTextChanged(Editable s) {boolean isVisible=getText().toString().length()>=1;setClearDrawableVisible(isVisible);}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count,int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before,int count) {}}   //隐藏或者显示右边clean的图标protected void setClearDrawableVisible(boolean isVisible) {Drawable rightDrawable;if (isVisible) {rightDrawable = mRightDrawable;} else {rightDrawable = null;}//使用代码设置该控件left, top, right, and bottom处的图标setCompoundDrawables(getCompoundDrawables()[0],getCompoundDrawables()[1], rightDrawable,getCompoundDrawables()[3]);} // 显示一个动画,以提示用户输入public void setShakeAnimation() {this.startAnimation(shakeAnimation(5));}//CycleTimes动画重复的次数public Animation shakeAnimation(int CycleTimes) {Animation translateAnimation = new TranslateAnimation(0, 10, 0, 10);translateAnimation.setInterpolator(new CycleInterpolator(CycleTimes));translateAnimation.setDuration(1000);return translateAnimation;}
}

自定义FrameLayout

public class KeywordsFlow extends FrameLayout implements OnGlobalLayoutListener {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;/** 由外至内的动画。 */public static final int ANIMATION_IN = 1;/** 由内至外的动画。 */public static final int ANIMATION_OUT = 2;/** 位移动画类型:从外围移动到坐标点。 */public static final int OUTSIDE_TO_LOCATION = 1;/** 位移动画类型:从坐标点移动到外围。 */public static final int LOCATION_TO_OUTSIDE = 2;/** 位移动画类型:从中心点移动到坐标点。 */public static final int CENTER_TO_LOCATION = 3;/** 位移动画类型:从坐标点移动到中心点。 */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 = 21;public static final int TEXT_SIZE_MIN = 14;private OnClickListener itemClickListener;private static Interpolator interpolator;private static AlphaAnimation animAlpha2Opaque;private static AlphaAnimation animAlpha2Transparent;private static ScaleAnimation animScaleLarge2Normal, animScaleNormal2Large,animScaleZero2Normal, animScaleNormal2Zero;/** 存储显示的关键字。 */private Vector<String> vecKeywords;private int width, height;/*** go2Show()中被赋值为true,标识开发人员触发其开始动画显示。<br/>* 本标识的作用是防止在填充keywrods未完成的过程中获取到width和height后提前启动动画。<br/>* 在show()方法中其被赋值为false。<br/>* 真正能够动画显示的另一必要条件:width 和 height不为0。<br/>*/private boolean enableShow;private Random random;/*** @see ANIMATION_IN* @see ANIMATION_OUT* @see OUTSIDE_TO_LOCATION* @see LOCATION_TO_OUTSIDE* @see LOCATION_TO_CENTER* @see CENTER_TO_LOCATION* */private int txtAnimInType, txtAnimOutType;/** 最近一次启动动画显示的时间。 */private long lastStartAnimationTime;/** 动画运行时间。 */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.decelerate_interpolator);animAlpha2Opaque = new AlphaAnimation(0.0f, 1.0f);animAlpha2Transparent = new AlphaAnimation(1.0f, 0.0f);animScaleLarge2Normal = new ScaleAnimation(2, 1, 2, 1);animScaleNormal2Large = new ScaleAnimation(1, 2, 1, 2);animScaleZero2Normal = 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;}/*** 开始动画显示。<br/>* 之前已经存在的TextView将会显示退出动画。<br/>* * @return 正常显示动画返回true;反之为false。返回false原因如下:<br/>*         1.时间上不允许,受lastStartAnimationTime的制约;<br/>*         2.未获取到width和height的值。<br/>*/public boolean go2Show(int animType) {if (System.currentTimeMillis() - lastStartAnimationTime > animDuration) {enableShow = true;if (animType == ANIMATION_IN) {txtAnimInType = OUTSIDE_TO_LOCATION;txtAnimOutType = 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 onAnimationEnd(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 + "---------------------------");LinkedList<Integer> listX = new LinkedList<Integer>(), listY = new LinkedList<Integer>();for (int i = 0; i < size; i++) {// 准备随机候选数,分别对应x/y轴位置listX.add(i * xItem);listY.add(i * yItem + (yItem >> 2));Log.e("Search", "ListX:" + (i * xItem) + "#listY:"+ (i * yItem + (yItem >> 2)));}// TextView[] txtArr = new TextView[size];LinkedList<TextView> listTxtTop = new LinkedList<TextView>();LinkedList<TextView> listTxtBottom = new LinkedList<TextView>();for (int i = 0; i < size; i++) {String keyword = vecKeywords.get(i);// 随机颜色// int ranColor = 0xff000000 | random.nextInt(0x0077ffff);// 随机位置,糙值int xy[] = randomXY(random, listX, listY, xItem);// 随机字体大小int txtSize = TEXT_SIZE_MIN+ random.nextInt(TEXT_SIZE_MAX - TEXT_SIZE_MIN + 1);// 实例化TextViewfinal TextView txt = new TextView(getContext());txt.setOnClickListener(itemClickListener);txt.setText(keyword);txt.setTextColor(Color.parseColor("#8cffffff"));txt.setTextSize(TypedValue.COMPLEX_UNIT_SP, txtSize);txt.setShadowLayer(1, 1, 1, 0xdd696969);txt.setGravity(Gravity.CENTER);// txt.setBackgroundColor(Color.RED);// 获取文本长度Paint paint = txt.getPaint();int strWidth = (int) Math.ceil(paint.measureText(keyword));xy[IDX_TXT_LENGTH] = strWidth;// 第一次修正:修正x坐标if (xy[IDX_X] + strWidth > width - (xItem >> 1)) {int baseX = width - strWidth;// 减少文本右边缘一样的概率xy[IDX_X] = baseX - xItem + random.nextInt(xItem >> 1);} else if (xy[IDX_X] == 0) {// 减少文本左边缘一样的概率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;}/** 修正TextView的Y坐标将将其添加到容器上。 */private void attach2Screen(LinkedList<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]);// 第二次修正:修正y坐标int yDistance = iXY[IDX_Y] - yCenter;// 对于最靠近中心点的,其值不会大于yItem// 对于可以一路下降到中心点的,则该值也是其应调整的大小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];// y轴以中心点为分隔线,在同一侧if (yDistance * (kXY[IDX_Y] - yCenter) > 0) {// Log.d("ANDROID_LAB", "compare:" +// listTxt.get(k).getText());if (isXMixed(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) {// 取消默认值。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);// 已经调整过前i个需要再次排序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);// 动画AnimationSet animSet = getAnimationSet(iXY, xCenter, yCenter,txtAnimInType);txt.startAnimation(animSet);}}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 TranslateAnimation((-xy[IDX_X] + xCenter), 0, (-xy[IDX_Y] + yCenter), 0);animSet.addAnimation(translate);}animSet.setDuration(animDuration);return animSet;}/*** 根据与中心点的距离由近到远进行冒泡排序。* * @param endIdx*            起始位置。* @param txtArr*            待排序的数组。* */private void sortXYList(LinkedList<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);}}}}/** A线段与B线段所代表的直线在X轴映射上是否有交集。 */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, LinkedList<Integer> listX,LinkedList<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();}/** 直接清除所有的TextView。在清除之前不会显示动画。 */public void rubAllViews() {removeAllViews();}public void setOnItemClickListener(OnClickListener listener) {itemClickListener = listener;}}

整个呈现效果还是满美观的,然后具体内容可以看源码,拿来就能用
源码地址:http://yunpan.cn/cdDvx3Zi9iA5m 访问密码 b1b7 (已失效)

可借鉴仓库:https://github.com/wenhuaijun/KeywordsFlowView

Android 好看的搜索界面,大赞Animation相关推荐

  1. android 仿 ios 搜索界面跳转效果

    最新写项目的时候,看到搜索界面的跳转基本都是点击搜索然后跳转到下个页面,android 微信上则是 类似toolbar的效果,而ios 上则是一个搜索框上移然后显示新界面的一个效果.仔细研究了下发现和 ...

  2. android 多条件搜索界面,SearchView实现搜索功能

    SearchView是安卓自带的搜索控件,可以帮助我们省下很多功夫.SearchView提供的api很多,但是麻烦在于SearchView的默认样式很多情况下不满足我们的开发需求,需要我们进行去进行定 ...

  3. Android 好看的登录界面

    例图1: 例图2: 例图3: 例图4: 例图5:

  4. 百度搜索低调改版搜索界面!

    近日,百度搜索界面大改版,新增右侧信息推荐和广告位,按钮和搜索框转向小清新风格! 最近不知道有站长发现没有,没有任何宣传,百度搜索最近低调的将自家搜索界面给改版了,改版后的整体搜索框和按钮都转向了偏向 ...

  5. Android软件开发之盘点自定义View界面大合集(二)

    Android软件开发之盘点自定义View界面大合集(二) - 雨松MOMO的程序世界 - 51CTO技术博客 雨松MOMO带大家盘点Android 中的自定义View界面的绘制 今天我用自己写的一个 ...

  6. Android搜索关键字飞入飞出效果(播放器的搜索界面)

    好多应用在搜索界面都有关键字飞入飞出的效果.我自己也实现了下.先上效果图: 实现该效果需要解决以下五点: 1.布局的选用. 2.确定动画区域,即布局的宽高. 3.对关键字坐标的随机分配. 4.对随机分 ...

  7. Android学习之登陆界面设计(二)基本界面设计

    Android学习之登陆界面设计(二)基本界面设计 前提 绘图样式 - drawable bg_login_btn_submit.xml bg_login_panel_slide.xml bg_log ...

  8. android 很多牛群叉界面库github地址

    android 很多牛叉界面库github地址 点击可到达github-------https://github.com/Trinea/android-open-project Android开源项目 ...

  9. android 很多牛叉界面库github地址

    点击可到达github-------https://github.com/Trinea/android-open-project 包括ListView.ActionBar.Menu.ViewPager ...

最新文章

  1. 一种神经元探索系统方法及装置
  2. 使用估算器、tf.keras 和 tf.data 进行多 GPU 训练
  3. 视频会议系统在企业网络中的关键利益—Vecloud微云
  4. 大规模数据中心如何重塑整个IT
  5. python(numpy,pandas4)——numpy中array合并和分割
  6. java打印6个偶数_Java编写一个应用程序,打印所有偶数从2到100
  7. 计算机图形学-MFC界面分屏操作
  8. UML 中extend和include的区别
  9. HDU3507-Print Article-斜率dp入门题
  10. Git工具项目管理的基础使用方式(GitHub同步方式)
  11. ping 代理_linux命令行代理神器-proxychains
  12. 编译器的差别gcc和VS
  13. 屏幕共享软件都有什么功能呢?
  14. CAD:计算三角形的外接圆圆心
  15. 套路得人心之我的运营之路!(文末有福利)
  16. bio-linux软件包教程,biolinux包含软件
  17. excel快速删除奇偶数行
  18. 数字IC设计----MOS管与逻辑门
  19. 2021-09-10 LeetCode1894-找到需要补充粉笔的学生编号(每日一题)
  20. 沐风:了不起的便利店

热门文章

  1. 有关nano安装Arduino
  2. 【IIOT】西门子PLC数采之S7-200
  3. 信捷xd5接线图_信捷XD5系列可编程控制器
  4. android安卓音乐播放器课程代码9.5.2
  5. 无需专业设备和技能修复AOC显示器
  6. swift cell的高度是动态的 三个文件:控制器 cell Frame类
  7. 容量法和库仑法的异同点_卡尔-费休容量法与库仑法的区别
  8. 用transition实现轮播图无缝衔接
  9. 180年魔鬼训练!人工智能打Dota 2 轻松打倒人类
  10. COGNEX扫码枪IO接线