編輯:關於Android編程
先看下效果吧
vcrH1+7E0bXEoaO+zcjDztLDx7+qyry7rbXa0ru49sz1xL+wyaOswvWz9tXi1+7E0bXE0ruyvTwvcD4NCjxwPruttdrSu7j2zPXEv6OsztLDx9Ky0qrPyLfWzvbPwtT1w7S7raOsytfRoc7Sw8fSqsi3tqjSu7j2zPXEv7XEv+22yLjftsijrL/ttsjV4sDvysfGwcS7tcS/7bbIo6y437bIuduy7MzUsaa1xM7vwfe/2Lz+o6zM9cS/tcS437bI08nJz835z8LKx9PJICZyc3F1bzvQxc+ivuDA68z1xL+2pbK/tcRtYXJnaW4gKyDQxc+itcS437bIICsgyrG85LrN0MXPorXEbWFyZ2luICsgyrG85LXEuN+2yCArIMqxvOS+4MDrzPXEv7XXsr+1xG1hcmdpbiZsc3F1bzsgubmzyaGjyLe2qMHLuN+2yKOhvdPXxc7Sw8e+zb/J0tS7rcHLo6zPyLutxMS49rarzvfL5tLiyseyu8rHo6zL+dLUwLS/qsq8u62wyTwvcD4NCjxwcmUgY2xhc3M9"brush:java;">
public class WuliuView extends View {
private int mMaginTop; //物流信息距離頂部magin
private int mMaginMsg; //時間距離物流信息magin
private int mWidth; //屏幕寬度
private int mLineWidth; //豎直線占條目的寬度
private TextPaint mTextPaint; //畫物流信息的畫筆
private int mTextHeight; //物流信息的高度
private int mMaginBottom; //時間距離條目底部的寬度
private int mHeight; //條目高度
private StaticLayout mStaticLayout;
private Rect mBound;
private String mMsg;
private Paint mTimePaint; //時間畫筆
private int mTimeHeight; //時間文字高度
public WuliuView(Context context) {
super(context);
init();
}
public WuliuView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public WuliuView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mMaginTop = dp2px(15); //15dp
mMaginBottom = mMaginTop;
mMaginMsg = dp2px(5); //時間和信息距離5dp
mLineWidth = dp2px(40); //豎直線占40dp
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); //抗鋸齒
mTextPaint.setDither(true); //仿抖動
mTextPaint.setColor(0xFF00FF00);
mTextPaint.setTextSize(dp2px(13)); //
mTextPaint.setTextAlign(Paint.Align.LEFT); //左下角對齊
mMsg = "【大天朝】已經簽收,簽收人是趙日天";
mBound = new Rect(); //通過邊框可以獲得文字的高度
mTextPaint.getTextBounds(mMsg, 0, mMsg.length(), mBound);
mTextHeight = mBound.height(); //得到文字高度
mTimePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTimePaint.setDither(true);
mTimePaint.setColor(0xFF00FF00);
mTimePaint.setTextSize(dp2px(10));
mTimePaint.setTextAlign(Paint.Align.LEFT);
mTimePaint.setTypeface(Typeface.DEFAULT_BOLD);
Rect boun = new Rect(); //同上理得到時間文字的高度
mTimePaint.getTextBounds("7",0,1,boun);
mTimeHeight = boun.height();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = mMaginTop + mTextHeight + mMaginMsg + mTimeHeight + mMaginBottom;//條目高度
setMeasuredDimension(mWidth, mHeight); //由此確定條目的高度
}
//
@Override
protected void onDraw(Canvas canvas) {
mTimePaint.setColor(0xFF00FF00);
canvas.drawText(mMsg,mLineWidth,mMaginTop+mTextHeight,mTextPaint); //畫信息
canvas.drawText(getFormateTime(new Date(System.currentTimeMillis())), mLineWidth, mMaginTop + mTextHeight +
mMaginMsg + mTimeHeight, mTimePaint);//畫時間
mTimePaint.setColor(Color.GRAY);//左邊那條線 //參數一線起點x坐標,參數二線起點y坐標,參數3,4是終點坐標
canvas.drawLine(mLineWidth/2,mMaginTop + mBound.height(),mLineWidth/2,mHeight,mTimePaint);
mTimePaint.setColor(0x550AE93E);//外面的更大的圓,但帶點透明
canvas.drawCircle(mLineWidth/2,mMaginTop + mBound.height() /2,mBound.height()/2,mTimePaint);
mTimePaint.setColor(0xFF00FF00); //內部更小的圓不透明和外面圓形成光暈
canvas.drawCircle(mLineWidth/2,mMaginTop + mBound.height() /2,mBound.height()/2 - dp2px(2),mTimePaint);
mTimePaint.setColor(Color.GRAY); //畫底部那條線
canvas.drawLine(mLineWidth,mHeight,mWidth,mHeight,mTimePaint);
}
public int dp2px(float dp) {
return (int) (getResources().getDisplayMetrics().density * dp + .5f);
}
public String getFormateTime(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
}
這樣一看,好像解決了是不是,我們來試試多一點文字看一看
mMsg = "【大天朝】已經簽收,簽收人是趙日天,感謝使用飛毛腿快遞,期待再次為您服務什麼鬼啊,我了個去,你大爺的啊,怎麼會這樣子呢,一點都不科學13177786453sdawdsadwfawadwawddfsa";
我靠,不換行啊,是不是瞬間感覺谷歌太不靠譜了。。。。然後這裡我也不會了,但是textview是View啊,它可以支持換行,所以一定有換行的方法,點進去看看源碼,我了個草,谷歌的當然是大神,但是再大的神,尼瑪那代碼也不忍直視,基本沒注釋,有注釋也是英文不詳細,沒過六級的表示壓力有點大,上網搜吧,去網上搜說StaticLayout這個東東可以換行,所以這個問題就可以解決了,來看看這個東東的用法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mStaticLayout = new StaticLayout(mMsg,
mTextPaint, mWidth - mLineWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 1.0f, false);
mTextHeight = mStaticLayout.getHeight();
mHeight = mMaginTop + mTextHeight + mMaginMsg + mTimeHeight + mMaginBottom;//條目高度
setMeasuredDimension(mWidth, mHeight); //由此確定條目的高度
}
//
@Override
protected void onDraw(Canvas canvas) {
mTimePaint.setColor(0xFF00FF00);
canvas.save();
canvas.translate(mLineWidth, mMaginTop);
mStaticLayout.draw(canvas); //畫信息
canvas.restore();
canvas.drawText(getFormateTime(new Date(System.currentTimeMillis())), mLineWidth, mMaginTop + mTextHeight +
mMaginMsg + mTimeHeight, mTimePaint);//畫時間
先看構造函數
mStaticLayout = new StaticLayout(mMsg,
mTextPaint, mWidth - mLineWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 1.0f, false);
第一個參數是要畫的信息;第二個參數是對應的畫筆;第三個參數是畫一行的長度;第四個是畫的方式,正常就是從左上角開始畫,我們原來的canvas.drawText默認是從左下角開始畫的;第五個參數,網上人說是列間距,第六個參數網上說是行間距,第七個不解,後面這三個參數對於我們這個控件沒影響,我也不知道干嘛用的,我改變了參數值好像沒什麼變化啊,我沒看出來,點進去看源碼也沒有介紹,所以真心覺得是大坑。。。然後來看它在onDraw是怎麼畫的
canvas.save();
canvas.translate(mLineWidth, mMaginTop);
mStaticLayout.draw(canvas); //畫信息
canvas.restore();
這裡canvas.translate(mLineWidth, mMaginTop);畫板要下移mMaginTop是因為StaticLayout.draw(canvas)默認是在畫板的(0,0)點畫的,我們修改不了畫的點,而且它是從字的左上角開始畫的,所以根據我們畫的物流信息是要距離條目頂部mMaginTop的距離,距離左邊mLineWidth,所以畫板下移mMaginTop,右移mLineWidth這時就畫在我們像畫的那個位置了,畫完後,再讓畫板canvas.restore();恢復原來canvas.save();的位置,這裡可能有人會想,畫板都移回去了,那不是物流信息也移回去了,你前面還移個什麼勁浪費表情。這裡是不對的,其實畫板每次畫一個東西是畫在一個圖層上而不是畫在畫板上的,畫板一開始默認和你的view坐標系一樣,這兩者之間有一個圖層,我們每次畫一個東西,畫在這個圖層上,然後圖層在顯示在view上,當再畫一個東西的時候,又有一個新的圖層再中間,畫完,在與原來的view結合形成新的view。依次循環。因為我們的StaticLayout.draw(canvas)它只能畫在畫板的(0,0)點,一開始畫板與圖層坐標系對應,所以當我們把它canvas.translate(mLineWidth, mMaginTop)這樣子畫板的(0.0)點就對應圖層的(mLineWidth, mMaginTop)的點了,畫是畫在圖層上的,不是畫在畫板上的,所以這正是我們想要的!。一般我們是不會去移的,因為坐標系對應,這裡沒辦法只能移,後面畫的東西坐標系要對應,所以我們要恢復,讓它坐標系對應。好了,這就是我的理解,說了這麼多來看看效果吧
對了,我上面的文字高度改成了這樣
mTextHeight = mStaticLayout.getHeight();
因為通過mBoung.hright()獲得的只是一行的高度。 嗯,看到效果圖發現有問題,很難看是不是,是這樣子的StaticLayout不允許字母截斷,什麼鳥意思呢,就是說它很聰明,認為你的字母是一個單詞,截斷了就破壞意思了!改改吧
mMsg = "【大天朝】已經簽收,簽收人是趙日天,感謝使用飛毛腿快遞,期待再次為您服務什麼鬼啊,我了個去,你大爺的啊,怎麼會這樣子呢,一點都不科學13177786453saddfsa";
當然我們的物流信息也不會有那麼多字母,說實話,我就沒看過超過三個字母。好了,最難得一步是不是被我們完成了。其實就是這麼簡單是不是。沒做過真的不知道啊。然後就是畫多條條目了,這我就直接貼代碼了吧,裡面也有注釋。有興趣的要下載源碼的,我會在審核通過後再評論區把下載路徑貼出來
/**
* Created by Root on 2016/7/8.
*/
public class WuliuView extends View {
private int mMaginTop; //物流信息距離頂部magin
private int mMaginMsg; //時間距離物流信息magin
private int mWidth; //屏幕寬度
private int mLineWidth; //豎直線占條目的寬度
private TextPaint mTextPaint; //畫物流信息的畫筆
private int mTextHeight; //物流信息的高度
private int mMaginBottom; //時間距離條目底部的寬度
private int mHeight; //條目高度
private Rect mBound;
private String mMsg;
private Paint mTimePaint; //時間畫筆
private int mTimeHeight; //時間文字高度
private ArrayList mDatas;
private ArrayList mStaticLayoutList;
public WuliuView(Context context, ArrayList datas) {
super(context);
init(datas);
}
private void init(ArrayList datas) {
mMaginTop = dp2px(15);
mMaginBottom = mMaginTop;
mMaginMsg = dp2px(5); //時間和信息距離5dp
mLineWidth = dp2px(40);
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setDither(true);
mTextPaint.setColor(0xFF00FF00);
mTextPaint.setTextSize(dp2px(13));
mTextPaint.setTextAlign(Paint.Align.LEFT);
mMsg = "【大天朝】已經簽收,簽收人是趙日天,感謝使用飛毛腿快遞,期待再次為您服務什麼鬼啊,我了個去,你大爺的啊,怎麼會這樣子呢,一點都不科學13177786453sdaw";
mBound = new Rect();
mTextPaint.getTextBounds(mMsg, 0, mMsg.length(), mBound);
mTimePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTimePaint.setDither(true);
mTimePaint.setColor(0xFF00FF00);
mTimePaint.setTextSize(dp2px(10));
mTimePaint.setTextAlign(Paint.Align.LEFT);
mTimePaint.setTypeface(Typeface.DEFAULT_BOLD);
Rect boun = new Rect();
mTimePaint.getTextBounds("7",0,1,boun);
mTimeHeight = boun.height();
mDatas = datas; //物流數據
mStaticLayoutList = new ArrayList();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mStaticLayoutList.clear(); //這裡會重復測量幾次,所以我們每次進來的時候需要清零一下
mHeight = 0;
for (int i = mDatas.size() - 1; i >= 0; i--) { //因為數據要從後面時間的往前面的時間繪制
mStaticLayoutList.add(new StaticLayout(mDatas.get(i).mMsg,mTextPaint,mWidth - mLineWidth, Layout
.Alignment.ALIGN_NORMAL,1.0f,1.0f,true));
}
for (int i = 0; i < mStaticLayoutList.size(); i++) { //每個條目的高度
mTextHeight = mStaticLayoutList.get(i).getHeight();
mHeight += mMaginTop + mTextHeight + mMaginMsg + mTimeHeight +mMaginBottom; //從左到右依次為最頂上margin,描述信息高度,時間與描述的margin,時間文字高度,與底部的margin
}
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
mHeight = 0;
for (int i = 0; i < mStaticLayoutList.size(); i++) {
StaticLayout staticLayout = mStaticLayoutList.get(i);
if (i == 0){ //第一次因為要改變一些顏色,所以這裡簡單點直接分開處理
mTimePaint.setColor(0xFF00FF00);
mTextPaint.setColor(0xFF00FF00);
canvas.save();
canvas.translate(mLineWidth, mMaginTop);
staticLayout.draw(canvas); //畫描述信息
canvas.restore();
mTextHeight = staticLayout.getHeight();
mHeight += mMaginTop + mTextHeight + mMaginMsg + mTimeHeight + mMaginBottom;
canvas.drawText(mDatas.get(i).mTime, mLineWidth, mHeight - mMaginBottom, mTimePaint);
mTimePaint.setColor(Color.GRAY);
canvas.drawLine(mLineWidth/2,mMaginTop + mBound.height(),mLineWidth/2,mHeight,mTimePaint); //豎直線
mTimePaint.setColor(0x550AE93E);
canvas.drawCircle(mLineWidth/2,mMaginTop + mBound.height() /2,mBound.height()/2,mTimePaint);//最近的信息圓,帶透明
mTimePaint.setColor(0xFF00FF00);
canvas.drawCircle(mLineWidth/2,mMaginTop + mBound.height() /2,mBound.height()/2 - dp2px(2),
mTimePaint);//小一點,不透明
mTimePaint.setColor(Color.GRAY);
canvas.drawLine(mLineWidth,mHeight,mWidth,mHeight,mTimePaint);//底部線
mTextPaint.setColor(Color.GRAY);
}else { //不是第一個條目,這裡不改變顏色了
canvas.save();
canvas.translate(mLineWidth, mMaginTop + mHeight);
staticLayout.draw(canvas);
canvas.restore();
mTextHeight = staticLayout.getHeight();
int addHeight = mMaginTop + mTextHeight + mMaginMsg + mTimeHeight + mMaginBottom;
mHeight += addHeight;
canvas.drawText(mDatas.get(i).mTime, mLineWidth, mHeight - mMaginBottom, mTimePaint); //畫時間
// 起點橫坐標 起點縱坐標 終點橫坐標 終點縱坐標
canvas.drawLine(mLineWidth/2,mHeight - addHeight,mLineWidth/2,mHeight,mTimePaint); //豎直線
canvas.drawLine(mLineWidth,mHeight,mWidth,mHeight,mTimePaint);//底部線
}
}
}
public int dp2px(float dp) {
return (int) (getResources().getDisplayMetrics().density * dp + .5f);
}
public String getFormateTime(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
}
Activity狀態保存應用及Activity的主題皮膚學習 1.Activity狀態的保存. Activi
前言Android的源碼公開策略豐富了手持設備的多樣性,但隨之而來的卻是較為嚴重的”碎片化”——版本繁多、尺寸多樣、功能定
最近公司的軟件需要改國際版,需要Facebook和Twitter的登錄和分享。本人先用Umeng的第三方社會化分享實現了該功能,但是後來一想問題來了,經過查證。Umeng
一、著色游戲概述近期群裡偶然看到一哥們在群裡聊不規則圖像填充什麼四聯通、八聯通什麼的,就本身好學務實的態度去查閱了相關資料。對於這類著色的資料,最好的就是去搜索些相關ap