菜鸟流程-Touching App(1)- 主界面

接下来我会把本身写Touching App的过程一一写下来,不过因为刚上路,可能还有不少错误,包括博客也是~~ 小事情啦,开心就好n(≧▽≦)n前端

这个app准备用来接收单片机传来的数据,而后显示在手机上,对环境进行评价。java

下面进入正题啦。android

1、界面元素分析

先看一下美工给个人图:web

美工主界面 图片

是基于常见的1280*720像素的图片。canvas

很显然,这个图片是有三部分构成的,上面的按钮层,中间的圆环,底部的数据展现。最难的应该是中间的圆环,因此我是先从这一部分开始的。数组


2、主界面_中部圆环实现

其实写过了以后回头看仍是很简单,虽然好像原本就不难、、、
须要实现的是一个自定义view,外面一个大的黑色圆环,里面一个小的彩色圆环,中间是接收到的数据,暂时让数据一直增长。app

2.1 先来实现中间的圆环吧

效果是这样的ide

中部圆环图片

其实也很简单,稍微困难一点的地方在于外发光和位置的选择,下面上代码,而后一步步说。svg

package com.example.blogcircle;

import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;


public class MyCircle extends View {

    private  int CircleWidth = 10; //圆环的宽度
    private int mCircleRadius = 223;// 圆环半径

    private static int mBlurRadius = 10;//外发光半径
    private static android.graphics.BlurMaskFilter.Blur mBlurStyle = android.graphics.BlurMaskFilter.Blur.SOLID;//外发光方式

    private Paint mBackCirclePaint;//黑环画笔
    private Paint mFrontCirclePaint;//彩环画笔

    public MyCircle(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyCircle(Context context) {
        super(context);
    }

    public MyCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void init() {
        //初始化黑环画笔
        mBackCirclePaint = new Paint();
        mBackCirclePaint.setAntiAlias(true);
        mBackCirclePaint.setColor(0xFF000000);
        mBackCirclePaint.setStyle(Paint.Style.STROKE);
        mBackCirclePaint.setStrokeWidth(CircleWidth);

        //初始化彩环画笔
        mFrontCirclePaint = new Paint();
        mFrontCirclePaint.setAntiAlias(true);
        mFrontCirclePaint.setColor(0xFF47B7FF);
        mFrontCirclePaint.setStyle(Paint.Style.STROKE);
        mFrontCirclePaint.setStrokeWidth(CircleWidth);
        mFrontCirclePaint.setMaskFilter(new BlurMaskFilter(mBlurRadius,
                mBlurStyle));
    }


    @Override
    protected void onDraw(Canvas canvas) {
        init();
        super.onDraw(canvas);

        float rectL = 360 - mCircleRadius
                - CircleWidth / 2;
        float rectT = 501 - mCircleRadius
                - CircleWidth / 2;
        float rectR = 360 + mCircleRadius
                + CircleWidth / 2;
        float rectB = 501 + mCircleRadius
                + CircleWidth / 2;


        // 画背后的黑色圆环
        RectF rectCircle1 = new RectF(rectL, rectT, rectR, rectB);
        Path path1 = new Path();
        path1.addArc(rectCircle1, 0, 360);
        canvas.drawPath(path1, mBackCirclePaint);


        // 画前面的彩色圆环
        Path path2 = new Path();
        path2.addArc(rectCircle1, -90, 90);
        canvas.drawPath(path2, mFrontCirclePaint);

    }

}

在这一部分暂时没有考虑那么多,位置什么直接根据美工给的图算出来的距离,主要是实现了彩色圆环的外发光。
在实现外发光的时候其实只须要添加一排代码就够了,就是在初始化彩色画笔的那里。布局

mFrontCirclePaint.setMaskFilter(new BlurMaskFilter(mBlurRadius,
                mBlurStyle));

可是这里还有个坑,当时坑了我很久,那就是要关闭硬件加速,要否则没有外发光的效果,须要在manifest文件中进行关闭。
下面是manifest文件中activity部分的代码,核心也就是一句:

<activity android:name="com.example.blogcircle.MainActivity" android:label="@string/app_name" android:hardwareAccelerated="false" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />                
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

到这里呢,就实现了中间有圆环了。

2.2 而后加上中间的数字以及下面的英文评价

效果图是下面这样的
这里写图片描述

其实这里应该放一个动图,不过我不会、、、
就是数字从0到100不停变化,彩色圆环随数字的变化而变化,下面的单词也在变化。

难点呢,就是数字的变化由于是模拟从单片机接收数据,因此应该放在另外一个类里面进行变化,而后传给自定义View类。另外一个难点就是数字和字母的居中显示,由于字母的长度,数字的长度在变化,因此不能用硬性的位置来计算了。

无论怎么样,先上完整代码,再说说我以为坑的地方。

package com.example.blogcircle;

import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;


public class MyCircle extends View {

    private  int CircleWidth = 10; //圆环的宽度

    private int mCircleRadius = 223;// 圆环半径
    private static int mBlurRadius = 10;
    private static android.graphics.BlurMaskFilter.Blur mBlurStyle = android.graphics.BlurMaskFilter.Blur.SOLID;

    private static int mNUM = 0;// 单片机传进来的数值
    private static String[] mLevel = { "unbearable", "bad", "soso", "easy",
            "comfort", "comfort" };

    private Paint mBackCirclePaint;
    private Paint mFrontCirclePaint;

    private Paint mNumPaint;
    private Paint mTextPaint;

    public MyCircle(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyCircle(Context context) {
        super(context);
    }

    public MyCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void init() {

        mBackCirclePaint = new Paint();
        mBackCirclePaint.setAntiAlias(true);
        mBackCirclePaint.setColor(0xFF000000);
        mBackCirclePaint.setStyle(Paint.Style.STROKE);
        mBackCirclePaint.setStrokeWidth(CircleWidth);

        mFrontCirclePaint = new Paint();
        mFrontCirclePaint.setAntiAlias(true);
        mFrontCirclePaint.setColor(0xFF47B7FF);
        mFrontCirclePaint.setStyle(Paint.Style.STROKE);
        mFrontCirclePaint.setStrokeWidth(CircleWidth);
        mFrontCirclePaint.setMaskFilter(new BlurMaskFilter(mBlurRadius,
                mBlurStyle));

        int textSize=150;
        mNumPaint=new Paint();
        mNumPaint.setAntiAlias(true);
        mNumPaint.setColor(0xFFFFFFFF);
        mNumPaint.setTextSize(textSize);

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(0xFFAAAAAA);
        textSize=40;
        mTextPaint.setTextSize(textSize);

    }


    @Override
    protected void onDraw(Canvas canvas) {
        init();
        super.onDraw(canvas);

        float rectL = 360 - mCircleRadius
                - CircleWidth / 2;
        float rectT = 501 - mCircleRadius
                - CircleWidth / 2;
        float rectR = 360 + mCircleRadius
                + CircleWidth / 2;
        float rectB = 501 + mCircleRadius
                + CircleWidth / 2;


        // 画背后的黑色圆环
        RectF rectCircle1 = new RectF(rectL, rectT, rectR, rectB);
        Path path1 = new Path();
        path1.addArc(rectCircle1, 0, 360);
        canvas.drawPath(path1, mBackCirclePaint);


        // 画前面的彩色圆环
        Path path2 = new Path();
        path2.addArc(rectCircle1, -90,  (int) (mNUM * 3.6));
        canvas.drawPath(path2, mFrontCirclePaint);

        // 数字居中:y就是 矩形中间的y值加上文字的descent,x就是 矩形中间的x值减去数字宽度的一半
        float numDescent=mNumPaint.getFontMetrics().descent;
        canvas.drawText(mNUM + "", 
            360 -mNumPaint.measureText(mNUM + "") / 2,
            501 + numDescent, 
            mNumPaint);
        // 文字居中,y就是数字的y加上数字的descent加上文字的ascent,x就是矩形中间的x值减去文字宽度的一半
        canvas.drawText(mLevel[mNUM / 20],
        360 - mTextPaint.measureText(mLevel[mNUM / 20]) / 2, 
        501+ numDescent * 2 -TextPaint.getFontMetrics().ascent,
        mTextPaint);
}

    public void setNum(int num) {
        mNUM = num;
        invalidate();

    }
}

先说init()方法。
增长了两个画笔,分别用来画数字和字母。
在变量里面有一个mNum,模拟单片机传进来的数值。
同时在变量里面声明了一个数组,用来对应不一样等级环境的评价,bad,soso这些,原本应该是只有五级的,不过我担忧数组溢出什么的,给它多弄了一个,不影响。

再说onDraw()方法里面的数字居中和文字居中部分。
首先固然是把它们画出来。
直接用canvas的drawText方法

void android.graphics.Canvas.drawText(String text, float x, float y, Paint paint)

里面有四个参数,分别是要画的文本,文本起始位置,基准线的位置,所使用的画笔。(可能有些不对的地方、、你们指出来就好,不要喷我~)
关键就是计算文本的x,y值。
x呢,就是屏幕中部减去文本宽度的一半,这样在水平方向就居中了,怎么实现的代码上也有。
y呢,就是在圆环中部的y值加上文本的descent距离。
关于文字的一些距离,我百度了好久,找到了这么一个图。
这里写图片描述
图片引用网址是这个:http://mikewang.blog.51cto.com/3826268/871765/
(引用别人的图以后这样说不知道是否是合适、、感受真的写起博客来好多问题啊-_-!)

其实我想加的不是这里的这个descent,是它上面的那一个,英文字母分布在四线格里,基准线是第三根线,因此想让文字垂直居中,应该是中间的y值加上一格的长度,不过呢,刚好就是这个descent值,因此就是这样了。

目前为止解决了为止问题,还有数字变化和圆环变化问题,圆环变化其实代码也就一句话。

// 画前面的彩色圆环
        Path path2 = new Path();
        path2.addArc(rectCircle1, -90, (int) (mNUM * 3.6));
        canvas.drawPath(path2, mFrontCirclePaint);

就是中间那句话,由于addArc()方法的三个参数分别是指矩形区域,开始的角度(从左向右水平为0度),和扫过的角度。由于数值为0对应-90度,100对应360度,因此只须要扫过代码中描述的那个值就能够了。

那这一部分剩下的就只有数字不停变化这个功能了。
在自定义View里面,对应的方法是setNum()。

public void setNum(int num) {
        mNUM = num;
        invalidate();
    }

这个方法是给其余类用的,由于数值是从其余类传进来的,在方法里面设置好数值以后,立马调用invalidate()更新UI。

接来下就要看一下MainActivity这个类里面的代码了。
完整的代码是下面这样的。

package com.example.blogcircle;

import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    Handler mHandler;
    TimerTask task;
    Timer timer;
    int mNum = 0;// 中间圆圈的值
    MyCircle myCircle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myCircle=(MyCircle)findViewById(R.id.myCircle);

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                if (msg.what == 0x123) {
                    myCircle.setNum(mNum);
                }

                super.handleMessage(msg);
            }

        };
        task = new TimerTask() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                // 将单片机的数值赋给mNUM
                mNum = getNum();

                Message msg = new Message();
                msg.what = 0x123;
                mHandler.sendMessage(msg);
            }
        };
        if(timer==null)
        timer = new Timer();
        timer.schedule(task, 1000, 200);

    }

 // 获得单片机传进来的数值
    protected int getNum() {
        if (mNum > 99) {
            mNum = 0;
        } else {
            mNum++;
        }
        return mNum;
    }
}

这里只要onCreate()方法和getNum()方法。

先说简单的,getNum()方法我打算后期完善的,就是模拟从单片机得到数值,因此这里就让类变量mNum不停加1,模拟的仍是很到位滴。也很简单,不说了。

再就是onCreate()方法了。思路就是,首先找到xml布局里的Mycircle控件,而后经过定时器不停的调用getNum()方法来使类变量mNum加1,而每次加1的同时会发送消息,调用MyCircle类的setNum变量,触发里面的invalidate,这样就达到了不停加1,不停更新UI的效果。

代码里面就是Timer,Task,Handler三个的配合,感受很经常使用,百度一下就会了~~

好,这样就差很少已经实现了大部分了,不过我给的效果图都是真机上的效果图,当我打开xml的图形界面的时候感受头很疼,由于它是这样的:
这里写图片描述

由于个人位置啊,距离啊全都是直接给的值,只能用在1280*720这个屏幕里面。

2.3 接下来到了关键环节了,也就是实现屏幕适配

我在这个环节遇到了好几个坑

首先,是如何实现屏幕适配
关于这个问题,我百度了好久,什么屏幕密度啊,屏幕分辨率啊,dip,dpi,dp,px乱七八糟的好多。。以后看到网上说,网页的前端没有这个问题是由于它们按照百分比写的界面,而后我决定这样作。

首先获取真实屏幕的宽度和高度,像素为单位。而后在代码里面按照比例进行缩放,eg,若是在宽720px的屏幕里面距离为10px,那么在360px里面距离应该为5px,代码为int margin=10*/720*360;

下面先上整个修改事后的,应该、适配屏幕的代码。

package com.example.blogcircle;

import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

public class MyCircle extends View {

    private  int CircleWidth = 10;
    private  int TextSize = 200;

    private final float WeightOfTitle = 0.09f;// 顶部栏所占高度权重
    private final float WeightOfView = 0.6f;// 自定义view所占高度权重

    private final float WeightOfCenterX = 0.5f;
    private final float WeightOfCenterY = 501.0f / 1280.0f;

    private int mCircleRadius = 223;// 圆环半径

    private int mScreenWidth;
    private int mScreenHeight;

    Typeface mTypeFace;

    private static int mNUM = 0;// 单片机传进来的数值
    private static String[] mLevel = { "unbearable", "bad", "soso", "easy",
            "comfort", "comfort" };

    private static int mBlurRadius = 10;
    private static android.graphics.BlurMaskFilter.Blur mBlurStyle = android.graphics.BlurMaskFilter.Blur.SOLID;

    private Paint mBackCirclePaint;
    private Paint mFrontCirclePaint;
    private Paint mNumPaint;
    private Paint mTextPaint;

    public MyCircle(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
    }

    public MyCircle(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    public MyCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void init() {
        DisplayMetrics dm = getResources().getDisplayMetrics();
        mScreenWidth = dm.widthPixels;
        mScreenHeight = dm.heightPixels;
        if((mScreenHeight/mScreenWidth)>(1280/720)){
            mCircleRadius=223*mScreenWidth/720;//圆环半径的适配
        }else{
            mCircleRadius=223*mScreenHeight/1280;
        }

        CircleWidth=Math.min(10*mScreenHeight/1280, 10*mScreenWidth/720);//圆环宽度的适配

        mBackCirclePaint = new Paint();
        mBackCirclePaint.setAntiAlias(true);
        mBackCirclePaint.setColor(0xFF000000);
        mBackCirclePaint.setStyle(Paint.Style.STROKE);
        mBackCirclePaint.setStrokeWidth(CircleWidth);

        mFrontCirclePaint = new Paint();
        mFrontCirclePaint.setAntiAlias(true);
        mFrontCirclePaint.setColor(0xFF47B7FF);
        mFrontCirclePaint.setStyle(Paint.Style.STROKE);
        mFrontCirclePaint.setStrokeWidth(CircleWidth);
        mFrontCirclePaint.setMaskFilter(new BlurMaskFilter(mBlurRadius,
                mBlurStyle));

        mNumPaint = new Paint();
        mNumPaint.setAntiAlias(true);
        mNumPaint.setColor(0xFFFFFFFF);

        int textSize=150*mCircleRadius/223;//数字大小的适配
        mNumPaint.setTextSize(textSize);

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(0xFFAAAAAA);
        textSize=40*mCircleRadius/223;//英语大小的适配
        mTextPaint.setTextSize(textSize);

    }


    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        init();
        super.onDraw(canvas);

        float rectL = mScreenWidth * WeightOfCenterX - mCircleRadius
                - CircleWidth / 2;
        float rectT = mScreenHeight * WeightOfCenterY - mCircleRadius
                - CircleWidth / 2;
        float rectR = mScreenWidth * WeightOfCenterX + mCircleRadius
                + CircleWidth / 2;
        float rectB = mScreenHeight * WeightOfCenterY + mCircleRadius
                + CircleWidth / 2;

        // 画背后的黑色圆环
        RectF rectCircle1 = new RectF(rectL, rectT, rectR, rectB);
        Path path1 = new Path();
        path1.addArc(rectCircle1, 0, 360);
        canvas.drawPath(path1, mBackCirclePaint);

        Path path2 = new Path();
        path2.addArc(rectCircle1, -90, (int) (mNUM * 3.6));//
        canvas.drawPath(path2, mFrontCirclePaint);

        // 数字居中:y就是 矩形中间的y值加上文字的descent,x就是 矩形中间的x值减去数字宽度的一半
        canvas.drawText(
                mNUM + "",
                mScreenWidth * WeightOfCenterX
                        - mNumPaint.measureText(mNUM + "") / 2, mScreenHeight
                        * WeightOfCenterY + mNumPaint.getFontMetrics().descent,
                mNumPaint);
        float numDescent = mNumPaint.getFontMetrics().descent;
        // 文字居中,y就是数字的y加上数字的descent加上文字的ascent,x就是矩形中间的x值减去文字宽度的一半
        canvas.drawText(
                mLevel[mNUM / 20],
                mScreenWidth * WeightOfCenterX
                        - mTextPaint.measureText(mLevel[mNUM / 20]) / 2,
                mScreenHeight * WeightOfCenterY + numDescent * 2
                        - mTextPaint.getFontMetrics().ascent, mTextPaint);
    }

    public void setNum(int num) {
        mNUM = num;
        invalidate();

    }


}

我感受这里主要就是思路的问题,直接提取两三句出来看看就好。

//一、直接算出比重的,以1280*720为基准。
private final float WeightOfCenterY = 501.0f / 1280.0f;
//二、直接进行变化的,根据现有屏幕和1280*720屏幕的比例。
if((mScreenHeight/mScreenWidth)>(1280/720)){
            mCircleRadius=223*mScreenWidth/720;//圆环半径的适配
        }else{
            mCircleRadius=223*mScreenHeight/1280;
        }
//三、其实和上面一种同样
int textSize=150*mCircleRadius/223;//数字大小的适配

其实都同样、就是以1280*720为基础进行缩放。

好了, 那屏幕适配这个坑就完成啦,哈哈哈哈。

接着,我发如今自定义view下面添加新的部件,在ui上看不见

好比我xml里面有个自定义View了,在下面紧接着来一个TextView,TextView会看不到。

这个着实坑了我有点久,结果发现就是自定义View的绘制流程不熟悉。。。
没有重写onMeasure()方法、、
这个方法是子部件用来告诉父部件“我须要多大的地方”的方法,若是没有重写的话,当自定义view没有规定特定大小的时候,会填充整个父类。
因为我没有重写,因此放在它下面的textView在屏幕以外,固然是看不到的,知道缘由就好说了,直接修改代码就ok啦,上修改的部分代码。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // TODO Auto-generated method stub
    setMeasuredDimension(measureWidth(widthMeasureSpec),// 600);
            measuredHeight(heightMeasureSpec));
    //Log.i("qx", "height:"+measuredHeight(heightMeasureSpec));
}

private int measuredHeight(int heightMeasureSpec) {
    // TODO Auto-generated method stub
    int result = 0;
    int specMode = MeasureSpec.getMode(heightMeasureSpec);
    int specSize = MeasureSpec.getSize(heightMeasureSpec);
    if (specMode == MeasureSpec.EXACTLY) {
        result = specSize;
    } else {
        result = (int) (mScreenHeight * WeightOfView);
        if (specMode == MeasureSpec.AT_MOST)
            result = Math.min(result, specSize);
    }

    return result;
}

private int measureWidth(int widthMeasureSpec) {
    // TODO Auto-generated method stub
    DisplayMetrics dm = getResources().getDisplayMetrics();
    mScreenWidth = dm.widthPixels;
    mScreenHeight = dm.heightPixels;


    int result = 0;
    int specMode = MeasureSpec.getMode(widthMeasureSpec);
    int specSize = MeasureSpec.getSize(widthMeasureSpec);

    if (specMode == MeasureSpec.EXACTLY) {
        result = specSize;
    } else {
        result = mScreenWidth;
        if (specMode == MeasureSpec.AT_MOST)
            result = Math.min(result, specSize);
    }

    return result;
}

对于这个方法细致的讲解呢、、这篇博客里面仍是不要讲好了,,我只是想概览的讲述一下写小项目的经历,也许之后会发真正的技术贴。

不过,只须要知道这样写了以后,这个自定义view只会包裹它该包裹的区域就行了。


3、主界面_底部数据和顶部按钮

因为写中部圆环的时候,吃了个亏,关于屏幕匹配的,因此我决定打死不用硬性的距离,包括dp也不用了,坚定拥护百分比制度。
因此我如今特别喜欢LinearLayout这个布局,由于它有weight这个属性~~
直接上布局代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FF1E2E3E" tools:context=".MainActivity" >

    <ImageButton  android:id="@+id/ibtn_left" android:scaleType="fitXY" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="@drawable/left_selector" />



    <ImageButton  android:id="@+id/ibtn_right" android:scaleType="fitXY" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:background="@drawable/right_selector" />

    <myView.MyViewCircleAdaption  android:id="@+id/myview_circle" android:layout_width="wrap_content" android:layout_height="wrap_content" />
    <!-- 蓝色的分割线 -->

    <View  android:id="@+id/line" android:layout_width="fill_parent" android:layout_height="1dp" android:layout_below="@id/myview_circle" android:layout_marginTop="20dp" android:background="#FF47B7FF" />

    <!-- 下方的数据展现界面 -->

    <LinearLayout  android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/line" android:background="@drawable/background_color" android:orientation="vertical" android:weightSum="7" >

        <!-- 空白 透明背景 -->

        <LinearLayout  android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="2" >

            <TextView  android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#00000000" />
        </LinearLayout>

        <!-- 水平展现,两个数字数据 -->

        <LinearLayout  android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="2" android:gravity="center_vertical" android:orientation="horizontal" >

            <!-- 左空白 -->

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3" android:background="#000000FF" />
            <!-- 温度 -->
            <!-- 数字 温度 -->

            <LinearLayout  android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" >

                <LinearLayout  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal" >

                    <TextView  android:id="@+id/tem" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:text="25 " android:textColor="#FFFFFFFF" android:textSize="30sp" />
                    <!-- 单位 温度 -->

                    <TextView  android:id="@+id/tem_danwei" android:layout_width="wrap_content" android:layout_height="wrap_content" android:alpha="0.5" android:background="#00000000" android:text="°C" android:textSize="30dp" />
                </LinearLayout>

                <TextView  android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:background="#00000000" android:text="Temprature" android:textSize="15sp" />
            </LinearLayout>
            <!-- 中间空白 -->

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="4" android:background="#000000FF" />
            <!-- 湿度 -->

            <LinearLayout  android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" >

                <LinearLayout  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal" >

                    <!-- 数字 湿度 -->

                    <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:text="75 " android:textColor="#FFFFFFFF" android:textSize="30dp" />

                    <!-- 单位 湿度 -->

                    <TextView  android:id="@+id/shidu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:alpha="0.5" android:background="#00000000" android:text="%RH" android:textSize="30dp" />
                </LinearLayout>

                <TextView  android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:background="#00000000" android:gravity="center_horizontal" android:text="Humicity" android:textSize="15sp" />
            </LinearLayout>
            <!-- 右空白 -->

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="2" android:background="#000000FF" />
        </LinearLayout>

        <!-- 水平展现,一个按钮 -->

        <LinearLayout  android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="2" android:gravity="center" >

            <Button  android:id="@+id/button_details" android:layout_width="191px" android:layout_height="57px" android:background="@drawable/button_selector" android:text="details" android:gravity="center" android:textColor="#ff37a7eF" android:textSize="20dp" />
        </LinearLayout>
    </LinearLayout>


</RelativeLayout>

顶部的按钮因为父组件是Relativelayout,不太方便直接在xml里面进行调整,要是用dp的话,对屏幕又不太适配了,因此我在java代码里面对它们进行了调整。就是下面这样:

btn_left = (ImageButton) findViewById(R.id.ibtn_left);
        LayoutParams params2 = (LayoutParams) btn_left.getLayoutParams();
        params2.width = (int) (65.95 * mScreenWidth / 720);
        params2.height = (int) (65.95 * mScreenHeight / 1280);
        btn_left.setX(58.1f * mScreenWidth / 720.0f);
        btn_left.setY(51.0f * mScreenHeight / 1280.0f);
        btn_left.setLayoutParams(params2);

这个是对左边设置按钮的调整,右边的相似,就不上了,真有想看我代码的同窗或者大牛能够在下面下载到~

而后上一下最终的效果图:
这里写图片描述
在320*480px的虚拟机上跑也是这个效果哦,hiahiahia~

好了,这个主界面好像差很少了,,

说老实话,写博客仍是有点累的,比写代码麻烦。。


界面源码下载地址:
http://download.csdn.net/download/qq_21922801/9615690