Android小知識10則(上) github傳送門 注: 在目錄中點選可以跳轉到具體代碼頁
目錄
- Chronometer的使用
- CountDownTimer的使用
- 矩形
- 橢圓
- 線
- 環
Android也是提供了計時器的, 雖然功能比較簡單, 但是有些場景下也還是夠用的...嗎?(手動滑稽) CountDownTimer是倒計時計時器. Chronometer的話, 看怎麼用了, 正着倒着都行...嗎?(再次滑稽)
禮貌性給下 官方文檔 . 然後上效果圖:
mTimer.setBase(-60000 + SystemClock.elapsedRealtime());
mTimer.setCountDown(false);
mTimer.start();
我們以+1m(也就是從1分鐘開始計時)為例:
- 先看xml代碼,
是要點, 後面會說. 然後它繼承自TextView, 屬性設定什麼的就很簡單了:
android:format="%s"
<Chronometer
android:id="@+id/timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="@dimen/sixteen_dp"
android:format="%s"
android:textColor="@android:color/darker_gray"
android:textSize="@dimen/thirty_sp" />
- (-60000 + SystemClock.elapsedRealtime())的出現會讓你一下子懵了, 是以先說SystemClock.elapsedRealtime(). Chronometer執行個體是需要設定基線的, 然後用SystemClock.elapsedRealtime()減去你設定的基線值, 換句話說, 如果你寫mTimer.setBase(SystemClock.elapsedRealtime());就意味着從零開始. 然後機關是ms, 一分鐘就是60000ms, 是以想從一分鐘開始就是(-60000 + SystemClock.elapsedRealtime())了.
- mTimer.setCountDown();代表是倒計時還是正常計時, false就是正常計時, true計時倒計時.
- 你可能會提問, 為什麼我沒有格式化字元串它也正常顯示了. 看xml中的
, 這就是代表用預設的格式. 官方文檔有這麼一段: By default it will display the current timer value in the form "MM:SS" or "H:MM:SS", or you can use setFormat(String) to format the timer value into an arbitrary string. 也就是說預設"MM:SS", 超過1小時"H:MM:SS", 你可以用setFormat(String)設定你的style兒(手動滑稽).
android:format="%s"
- 然後mTimer.start();是開始. mTimer.stop();是停止. 這很好了解了.
也許你會覺得它還挺好用, 但事實很殘酷, 倒計時的功能要7.0才能使用, 其它的倒是相容低版本, 但是廢了一半了不是. 但是配合CountDownTimer, 意外地解決了麻煩.
效果圖:
這個倒計時類異常好用. 構造函數第一個參數是總時長, 第二個是間隔. onTick是每次變化要執行的動作, onFinish是結束後要執行的動作.是開始.
mCountDownTimer.start();
是停止. 完事了, 就這麼多内容, 不信去看看 .
mCountDownTimer.cancel();
private CountDownTimer mCountDownTimer = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
String str = "剩餘" + (millisUntilFinished / 1000) + "秒";
mTvTime.setText(str);
}
@Override
public void onFinish() {
mTvTime.setEnabled(true);
mTvTime.setText("倒計時結束");
}
};
正規表達式是很通用的東西了, 不論寫什麼都會用到的, 看看應用中展現的部分正規表達式的功能吧:
規則
隻要知道了規則, 幾乎沒有正規表達式比對不了的串(手動滑稽). 這裡有個
推薦的網站 . 裡面寫的很細. 接下來展示如何在Android中實作的.- 比對
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("abcd1234ABCD5678");
上面兩行是關鍵語句, compile方法中的字元串就是正規表達式, 這裡是"\\d+"(注意多一個\是轉義符). matcher方法中的字元串就是要比對的字元串, 這裡是"abcd1234ABCD5678".
然後有4種比對方式, 我在效果圖中展示的是find()和matches():
序号 | 方法 | 說明 |
---|---|---|
1 | public boolean lookingAt() | 嘗試将從區域開頭開始的輸入序列與該模式比對。 |
2 | public boolean find() | 嘗試查找與該模式比對的輸入序列的下一個子序列。 |
3 | public boolean find(int start) | 重置此比對器,然後嘗試查找比對該模式、從指定索引開始的輸入序列的下一個子序列。 |
4 | public boolean matches() | 嘗試将整個區域與模式比對。 |
while (m.find()) {
Log.i("sorrower", m.group());
}
上面的代碼可以列印符合正規表達式的子序列結果. 當然你可以使用m.group(x)擷取第x個比對的子序列. 注意從1開始.
用m.start()和m.end()就可以擷取到子序列的起始位置和結束位置後面一個位置了.
matches()的傳回值表示整個比對是否成功.
替換
除開比對, 用正規表達式替換也是沒問題的哦.
public Matcher appendReplacement(StringBuffer sb, String replacement) | 實作非終端添加和替換步驟。 | |
public StringBuffer appendTail(StringBuffer sb) | 實作終端添加和替換步驟。 | |
public String replaceAll(String replacement) | 替換模式與給定替換字元串相比對的輸入序列的每個子序列。 | |
public String replaceFirst(String replacement) | 替換模式與給定替換字元串比對的輸入序列的第一個子序列。 | |
5 | public static String quoteReplacement(String s) | 傳回指定字元串的字面替換字元串。這個方法傳回一個字元串,就像傳遞給Matcher類的appendReplacement 方法一個字面字元串一樣工作。 |
來看看效果先吧!
轉變為靜态數組
首先是ArrayList轉變為靜态數組, 這個算是個小知識點吧, toArray方法中的參數要寫對. 代碼如下:
ArrayList<String> list = new ArrayList<>();
list.add("java");
list.add("c");
list.add("c++");
String[] strings = list.toArray(new String[0]);
Log.i("tag", Arrays.toString(strings));
在沒有UI設計師的時候, 或者是想簡單看下效果的時候, 用shape進行快速繪制是極好的! 大家如果之前有關注我, 會知道這是之前一個單獨的篇章, 當然不是為了湊數放在這裡的, 和下一個知識點有關. 一共有四種shape: rectangle, oval, line, ring.
我們一個一個來看, 首先是矩形:
矩形例子
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 尺寸 -->
<size
android:width="160dp"
android:height="80dp" />
<!-- 顔色 -->
<!--<solid android:color="@color/colorPrimary" />-->
<!-- 内間距 -->
<padding
android:bottom="8dp"
android:left="8dp"
android:right="8dp"
android:top="8dp" />
<!-- 漸變 -->
<gradient
android:angle="45"
android:endColor="@color/colorPrimary"
android:startColor="@color/colorAccent"
android:type="linear" />
<!-- 圓角 -->
<!--<corners android:radius="200dp" />-->
<!-- 圓角單獨設定 -->
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="40dp"
android:topRightRadius="40dp" />
<!-- 描邊 -->
<stroke
android:width="2dp"
android:color="#666"
android:dashGap="4dp"
android:dashWidth="4dp" />
</shape>
- 漸變gradient是會覆寫顔色的, 如果你想要純色, 直接設定顔色值即可, 就是設定solid中的color.
- 順帶一提, solid隻有color一個參數.
- 如果你沒有漸變gradient, 也不寫solid, 那麼将會是空心的.
- 漸變gradient的type參數有3個:
- linear 線性漸變
- sweep 掃描漸變
- radial 放射漸變, 需要配合參數gradientRadius
- 圓角corners可以直接設定radius, 也可以一個一個指定.
- 描邊stroke的話不寫dashGap, dashWidth就會是實線, dashWidth代表虛線寬度, dashGap代表虛線間隔.
- 内間距padding和尺寸size就不提了, 大家都懂的.
橢圓例子
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- 尺寸 -->
<size
android:width="160dp"
android:height="80dp" />
<!-- 顔色 -->
<!--<solid android:color="@color/colorPrimary" />-->
<!-- 内間距 -->
<padding
android:bottom="8dp"
android:left="8dp"
android:right="8dp"
android:top="8dp" />
<!-- 漸變 -->
<gradient
android:centerColor="@color/colorPrimary"
android:endColor="@color/colorPrimaryDark"
android:startColor="@color/colorAccent"
android:type="sweep" />
<!-- 描邊 -->
<stroke
android:width="1dp"
android:color="#333" />
</shape>
- 漸變是最多可以設定三種顔色, 意思一看便知了:
- startColor
- centerColor
- endColor
- 一般橢圓都會用來繪制實心的小圓點.
線就很簡單了:
線例子
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<!-- 描邊 -->
<stroke
android:width="8dp"
android:color="@color/colorPrimary"
android:dashGap="8dp"
android:dashWidth="6dp" />
</shape>
最後來看環, 它有些特有屬性:
環例子B
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadiusRatio="4"
android:shape="ring"
android:thicknessRatio="100"
android:useLevel="false">
<!-- 尺寸 -->
<size
android:width="200dp"
android:height="200dp" />
<!-- 漸變 -->
<gradient
android:angle="0"
android:centerColor="@color/colorPrimaryDark"
android:endColor="@color/colorPrimary"
android:startColor="@color/colorAccent"
android:type="sweep" />
<!-- 描邊 -->
<stroke
android:width="1dp"
android:color="#777"
android:dashGap="4dp"
android:dashWidth="4dp" />
</shape>
thicknessRatio
指的是環厚度百分比, 預設是9, 比如說這裡寬度是200dp, thicknessRatio是100, 環厚度就是200dp / 100 = 2dp. 當然, 你可以直接用thickness設定厚度.
innerRadiusRatio
是内環百分比, 預設是3, 就是指用寬度 / 百分比得到的值就是内環半徑. 同樣可以用innerRadius直接設定.
我知道有很多非常好看的自定義進度條, 但是我寫這個SeekBar是想補充下shape的使用, 用非常少量的代碼實作自定義進度條. 來看看效果圖:
- 實作
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/eight_dp"
android:max="200"
android:maxHeight="@dimen/eight_dp"
android:minHeight="@dimen/eight_dp"
android:progressDrawable="@drawable/layout_progress"
android:thumb="@drawable/shape_circle" />
簡單解釋下幾個要點屬性:
- max代表進度條最大的值.
- maxHeight, minHeight可以設定進度條寬度, 我喜歡稍微寬一點的.
- thumb設定滑塊, 可以是圖檔, 可以是shape寫的設定.
- progressDrawable代表進度條的外觀, 可以是圖檔, 可以是shape寫的設定.
再來看看滑塊和進度條外觀具體代碼, 進度條可以設定背景, 進度, 和第二進度. 滑塊的話, 你想畫成什麼樣都行.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="@dimen/four_dp" />
<solid android:color="@android:color/darker_gray" />
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="@dimen/four_dp" />
<solid android:color="@color/colorAccent" />
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="@dimen/four_dp" />
<solid android:color="@android:color/holo_blue_light" />
</shape>
</clip>
</item>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/holo_blue_light" />
<stroke
android:width="@dimen/one_dp"
android:color="@android:color/holo_blue_light" />
<size
android:width="@dimen/sixteen_dp"
android:height="@dimen/sixteen_dp" />
</shape>
java部分的話, 用Handler執行個體postDelayed方法讓進度條跑起來就可以看到效果了. 這裡設定50ms發一次消息.
findViewById(R.id.cv_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mRunnable == null) {
mRunnable = new MyRunnable();
mHandler.postDelayed(mRunnable, 0);
}
}
});
findViewById(R.id.cv_stop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mHandler.removeCallbacks(mRunnable);
mRunnable = null;
}
});
private class MyRunnable implements Runnable {
@Override
public void run() {
int progress = mSbTest.getProgress();
mTvProgress.setText(String.valueOf(progress));
mSbTest.setProgress(++progress);
mSbTest.setSecondaryProgress(progress + 10);
int progress2 = mSbTest2.getProgress();
mTvProgress2.setText(String.valueOf(progress2));
mSbTest2.setProgress(++progress2);
mSbTest2.setSecondaryProgress(progress2 + 20);
mHandler.postDelayed(this, 50);
}
}
這樣就寫完10個知識點了, 這樣之後很多文章擴充起來就會很友善了. 喜歡記得點贊, 有意見或者建議評論區見, 暗中關注我也是可以的哦~