菜鳥流程-Touching App(1)- 主介面
接下來我會把自己寫Touching App的過程一一寫下來,不過由於剛上路,可能還有很多錯誤,包括部落格也是~~ 小事情啦,開心就好n(≧▽≦)n
這個app準備用來接收微控制器傳來的資料,然後顯示在手機上,對環境進行評價。
下面進入正題啦。
一、介面元素分析
先看一下美工給我的圖:
是基於常見的1280*720畫素的圖片。
很顯然,這個圖片是有三部分構成的,上面的按鈕層,中間的圓環,底部的資料展示。最難的應該是中間的圓環,所以我是先從這一部分開始的。
二、主介面_中部圓環實現
其實寫過了之後回頭看還是很簡單,雖然好像本來就不難、、、
需要實現的是一個自定義view,外面一個大的黑色圓環,裡面一個小的彩色圓環,中間是接收到的資料,暫時讓資料一直增加。
2.1 先來實現中間的圓環吧
效果是這樣的
其實也很簡單,稍微困難一點的地方在於外發光和位置的選擇,下面上程式碼,然後一步步說。
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();
}
}
我感覺這裡主要就是思路的問題,直接提取兩三句出來看看就好。
//1、直接算出比重的,以1280*720為基準。
private final float WeightOfCenterY = 501.0f / 1280.0f;
//2、直接進行變化的,根據現有螢幕和1280*720螢幕的比例。
if((mScreenHeight/mScreenWidth)>(1280/720)){
mCircleRadius=223*mScreenWidth/720;//圓環半徑的適配
}else{
mCircleRadius=223*mScreenHeight/1280;
}
//3、其實和上面一種一樣
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只會包裹它該包裹的區域就好了。
三、主介面_底部資料和頂部按鈕
由於寫中部圓環的時候,吃了個虧,關於螢幕匹配的,所以我決定打死不用硬性的距離,包括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~
好了,這個主介面好像差不多了,,
說老實話,寫部落格還是有點累的,比寫程式碼麻煩。。