本人很喜欢机锋市场的界面风格,无论是网页仍是手机应用,老是能在偶然间给人眼前一亮的感受,因此一直想看看它究竟是怎么实现的,苦于找不到有介绍的文章,只好本身来了。本文主要是基于机锋android客户端的0.9.5beta版本,经过反编译来查看它的界面究竟是如何实现的,因为能力有限,因此不少东西不必定都正确,也不必定都是机锋市场的原始的实现,只能尽可能接近它的实现。有什么不对的地方,还请你们多多指点啊。html
那么就先从机锋市场的首页讲起,先来看图java
这个界面的内容就两块,一个是背景图片,还有一个就是横向的进度条,这个页面特别的地方就在这个进度条上了。这种进度条咱们在不少网站或是电脑上的软件都有见过,可是在android手机上咱们常见的仍是圆形的不断旋转的这种进度条,机锋的这个进度条我在手机上仍是第一次见。那么她是如何实现的呢...咱们先来看下它的布局文件(反编译出来的)android
<?xml version="1.0" encoding="UTF-8"?> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView android:id="@+id/iv_splashBg" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="matrix" /> <LinearLayout android:gravity="center" android:id="@+id/ll_loading" android:background="@drawable/toast_bg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="40.0dip" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true"> <TextView android:id="@+id/splash_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/init_data" style="\@style/text_style_1e" /> <ProgressBar android:id="@+id/splash_loading" android:layout_width="54.0dip" android:layout_height="wrap_content" android:minHeight="18dip" android:maxHeight="18dip" android:indeterminateOnly="true" /> </LinearLayout> </RelativeLayout>
在布局文件中没有见到特别的控件,都是系统自带的控件啊(事实上,当我看到机锋的进度条的时候,我想到了两种实现方法,一种就是帧动画,我画出7张图片来,经过真动画不断循环播放,这个理论上应该是能够的,不过不会ps没实现。还有一种就是本身定义一个控件,不断的进行重绘,来实现动画,下面是代码canvas
public class UserView extends View{ private Paint mPaint; private boolean flag = true; private int index = 0; private int direction = 0;//0 向右,1向左 private LoopThread loopThread; public UserView(Context context) { super(context); init(); } public UserView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public UserView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init(){ mPaint = new Paint(); mPaint.setColor(0xffC8C8C8); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int offect = 0; mPaint.setStyle(Style.FILL); for (int i = 0; i < 4; i++) { if(index==i){ mPaint.setColor(0xffFFB43C); offect = 2; }else{ mPaint.setColor(0xffC8C8C8); offect = 0; } canvas.drawRect(10 + 20*i -offect, 10 - offect, 20 + 20*i + offect, 20 + offect, mPaint); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(90, 30);//设置控件的高宽 } public void start(){ if(loopThread==null){ flag = true; loopThread = new LoopThread(); loopThread.start(); }else{ flag = false; loopThread.interrupt(); loopThread = new LoopThread(); flag = true; loopThread.start(); } } public void stop(){ if(loopThread!=null){ loopThread.interrupt(); } flag = false; } private int nextIndex(int index){ int i = 0; switch(direction){ case 0: if(index+1>3 ){ direction = 1; i = index-1; }else{ i = index+1; } break; case 1: if(index-1<0){ direction = 0; i = index+1; }else{ i = index-1; } break; } return i; } private class LoopThread extends Thread{ @Override public void run() { while(true){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } if(!flag) break; index = nextIndex(index); postInvalidate(); } } } }
也能实现,并且效果差很少,麻烦的地方,就是要本身控制线程。)
咱们再来看看它的源码(改动了一些)ide
progressBar.setIndeterminateDrawable(new LoadDrawable(4, 0xffC8C8C8, 0xffFFB43C));
只是对进度条设置了图片,关键点仍是在LoadDrawable这个类中(因为反编译后的源码有部分乱码,下面的源码都是我根据它实现的大概思路本身重写的,之后的源码也会有相似的状况)
public class LoadDrawable extends AnimationDrawable{ private int size = 4; private int width; private int height = 30; private Paint mPaint; private int defaultColor,currentColor; public LoadDrawable(int size,int defaultColor,int currentColor) { this.defaultColor = defaultColor; this.currentColor = currentColor; this.size = size; width = (size*2 + 1) * 10; mPaint = new Paint(); mPaint.setStyle(Style.FILL); initDrawable(); setOneShot(false); } private void initDrawable(){ for (int i = 0; i < size; i++) { addFrame(drawByIndex(i), 200); } for (int i = size-2; i > 0; i--) { addFrame(drawByIndex(i), 200); } } private Drawable drawByIndex(int index){ Bitmap b = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); int offect = 0; for (int i = 0; i < 4; i++) { if(index==i){ mPaint.setColor(currentColor); offect = 2; }else{ mPaint.setColor(defaultColor); offect = 0; } c.drawRect(10 + 20*i -offect, 10 - offect, 20 + 20*i + offect, 20 + offect, mPaint); } return new BitmapDrawable(b); } }
咱们发现事实上有点想我以前的两种方法的结合,自定义了一个AnimationDrawable类,又本身绘制了每一帧的图片。
这里注意下setOneShot(false)可使动画图片不断循环。oop
ok,这样机锋市场的首页就大功告成了啊布局
后面会陆续写些机锋市场界面的其余实现post