Android 好看的搜索界面,大赞Animation
###转载请注明出处王亟亟的大牛之路
一直对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相关推荐
- android 仿 ios 搜索界面跳转效果
最新写项目的时候,看到搜索界面的跳转基本都是点击搜索然后跳转到下个页面,android 微信上则是 类似toolbar的效果,而ios 上则是一个搜索框上移然后显示新界面的一个效果.仔细研究了下发现和 ...
- android 多条件搜索界面,SearchView实现搜索功能
SearchView是安卓自带的搜索控件,可以帮助我们省下很多功夫.SearchView提供的api很多,但是麻烦在于SearchView的默认样式很多情况下不满足我们的开发需求,需要我们进行去进行定 ...
- Android 好看的登录界面
例图1: 例图2: 例图3: 例图4: 例图5:
- 百度搜索低调改版搜索界面!
近日,百度搜索界面大改版,新增右侧信息推荐和广告位,按钮和搜索框转向小清新风格! 最近不知道有站长发现没有,没有任何宣传,百度搜索最近低调的将自家搜索界面给改版了,改版后的整体搜索框和按钮都转向了偏向 ...
- Android软件开发之盘点自定义View界面大合集(二)
Android软件开发之盘点自定义View界面大合集(二) - 雨松MOMO的程序世界 - 51CTO技术博客 雨松MOMO带大家盘点Android 中的自定义View界面的绘制 今天我用自己写的一个 ...
- Android搜索关键字飞入飞出效果(播放器的搜索界面)
好多应用在搜索界面都有关键字飞入飞出的效果.我自己也实现了下.先上效果图: 实现该效果需要解决以下五点: 1.布局的选用. 2.确定动画区域,即布局的宽高. 3.对关键字坐标的随机分配. 4.对随机分 ...
- Android学习之登陆界面设计(二)基本界面设计
Android学习之登陆界面设计(二)基本界面设计 前提 绘图样式 - drawable bg_login_btn_submit.xml bg_login_panel_slide.xml bg_log ...
- android 很多牛群叉界面库github地址
android 很多牛叉界面库github地址 点击可到达github-------https://github.com/Trinea/android-open-project Android开源项目 ...
- android 很多牛叉界面库github地址
点击可到达github-------https://github.com/Trinea/android-open-project 包括ListView.ActionBar.Menu.ViewPager ...
最新文章
- 一种神经元探索系统方法及装置
- 使用估算器、tf.keras 和 tf.data 进行多 GPU 训练
- 视频会议系统在企业网络中的关键利益—Vecloud微云
- 大规模数据中心如何重塑整个IT
- python(numpy,pandas4)——numpy中array合并和分割
- java打印6个偶数_Java编写一个应用程序,打印所有偶数从2到100
- 计算机图形学-MFC界面分屏操作
- UML 中extend和include的区别
- HDU3507-Print Article-斜率dp入门题
- Git工具项目管理的基础使用方式(GitHub同步方式)
- ping 代理_linux命令行代理神器-proxychains
- 编译器的差别gcc和VS
- 屏幕共享软件都有什么功能呢?
- CAD:计算三角形的外接圆圆心
- 套路得人心之我的运营之路!(文末有福利)
- bio-linux软件包教程,biolinux包含软件
- excel快速删除奇偶数行
- 数字IC设计----MOS管与逻辑门
- 2021-09-10 LeetCode1894-找到需要补充粉笔的学生编号(每日一题)
- 沐风:了不起的便利店