2012年12月1日 星期六
隱藏使用DialogFragment時會自動出會軟鍵盤
只要加入以下即可
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
2012年11月11日 星期日
使用Geocoder將經緯度轉地址
要把經緯度店址可以使用以下作法
Geocoder gc = new Geocoder(getActivity(), Locale.TRADITIONAL_CHINESE);
List<Address> lstAddress = gc.getFromLocation(lat, lng, 1);
String returnAddress=lstAddress.get(0).getAddressLine(0);
取地的結果會是全部的地址,如:100台灣台北市中正區信陽街33號
但取得的是全部的地址,但如果只是想取得城市等等,所以這邊自己記錄一下。
lstAddress.get(0).getCountryName(); //台灣省
lstAddress.get(0).getAdminArea(); //台北市
lstAddress.get(0).getLocality(); //中正區
lstAddress.get(0).getThoroughfare(); //信陽街(包含路巷弄)
lstAddress.get(0).getFeatureName(); //會得到33(號)
lstAddress.get(0).getPostalCode(); //會得到100(郵遞區號)
20121115補充:
也可以使用Json抓取資料後再顯示在Android上
網址為:
http://ditu.google.com/maps/geo?q=您的Latitude,您的Longitude&output=可以json或xml&oe=utf8&hl=zh-CN&sensor=true&key=您的Map APIkey
這樣我會得到以下內容,再對照取出也可以。
Geocoder gc = new Geocoder(getActivity(), Locale.TRADITIONAL_CHINESE);
List<Address> lstAddress = gc.getFromLocation(lat, lng, 1);
String returnAddress=lstAddress.get(0).getAddressLine(0);
取地的結果會是全部的地址,如:100台灣台北市中正區信陽街33號
但取得的是全部的地址,但如果只是想取得城市等等,所以這邊自己記錄一下。
lstAddress.get(0).getCountryName(); //台灣省
lstAddress.get(0).getAdminArea(); //台北市
lstAddress.get(0).getLocality(); //中正區
lstAddress.get(0).getThoroughfare(); //信陽街(包含路巷弄)
lstAddress.get(0).getFeatureName(); //會得到33(號)
lstAddress.get(0).getPostalCode(); //會得到100(郵遞區號)
20121115補充:
也可以使用Json抓取資料後再顯示在Android上
網址為:
http://ditu.google.com/maps/geo?q=您的Latitude,您的Longitude&output=可以json或xml&oe=utf8&hl=zh-CN&sensor=true&key=您的Map APIkey
這樣我會得到以下內容,再對照取出也可以。
{ "name": "25.03078,121.442786", "Status": { "code": 200, "request": "geocode" }, "Placemark": [ { "id": "p1", "address": "242台灣新北市新莊區新莊路751巷83號", "AddressDetails": { "Accuracy" : 8, "Country" : { "AdministrativeArea" : { "AdministrativeAreaName" : "新北市", "Locality" : { "DependentLocality" : { "DependentLocalityName" : "國泰裡", "PostalCode" : { "PostalCodeNumber" : "242" }, "Thoroughfare" : { "ThoroughfareName" : "新莊路751巷83號" } }, "LocalityName" : "新莊區" } }, "CountryName" : "台灣", "CountryNameCode" : "TW" } }, "ExtendedData": { "LatLonBox": { "north": 25.0320820, "south": 25.0293840, "east": 121.4441770, "west": 121.4414790 } }, "Point": { "coordinates": [ 121.4428280, 25.0307330, 0 ] } } ] }
2012年11月2日 星期五
2012年10月22日 星期一
Intent時二個畫面的生命週期
從Activity A Intent到Activity B時,二個畫面的生命周期以下自己做個紀錄。
- 從A intent 到 B時:
One onPause->
Two onCreate->Two onStart->Two onResume->
One onStop - 當B按返回鍵至A時:
Two onPause->
One onRestart->One onStart->One onResume->
Two onStop->Two onDestroy
2012年8月27日 星期一
點擊map上的標記時變更圖案
在map上點擊某個標記時,想讓該標記變更圖示,以便使用者辨別目前點選的項目,可以使用以下作法。
protected boolean onTap(int index) {
OverlayItem item = mOverlays.get(index);
//Get the new Drawable
Drawable marker = mContext.getResources().getDrawable(R.drawable.icon);
//Set its bounds
marker.setBounds(0,0,marker.getIntrinsicWidth(),marker.getIntrinsicHeight());
//Set the new marker
item.setMarker(marker);
//Return true! Do not invalidate
return true;
}
但如果你在ItemizedOverlay<OverlayItem>裡面原先是將Drawable設置為super(boundCenterBottom(defaultMarker))的話,會發現點擊後雖然變色了但是圖示移位了,這時在setBounds的地方必須設置以下(也就是boundCenterBottom的意思)
int dWidth = drawable.getIntrinsicWidth();
int dHeight = drawable.getIntrinsicHeight();
marker.setBounds(-dWidth / 2, -dHeight, dWidth / 2, 0);
做到這裡發現如果點擊下一個marker,上一個marker沒有變回來,我自己使用以下方式
OverlayItem item = items.get(arg0);
Drawable marker = context.getResources().getDrawable(R.drawable.map_pin);
Drawable markers = context.getResources().getDrawable(R.drawable.map_pins);
int dWidth = marker.getIntrinsicWidth();
int dHeight = marker.getIntrinsicHeight();
marker.setBounds(-dWidth / 2, -dHeight, dWidth / 2, 0);
markers.setBounds(-dWidth / 2, -dHeight, dWidth / 2, 0);
//如果點擊的跟之前點擊的物件不同,恢復上一支旗標的顏色,變更目前點選旗標顏色
if(arg0!=itemPotiion){
//恢復上一支旗標的顏色
if(itemPotiion!=-1){
OverlayItem before_item = items.get(itemPotiion);
before_item.setMarker(marker);
}
//變更目前旗標顏色
item.setMarker(markers);
}
itemPotiion=arg0;//記錄點選的項目
參考網址:
http://pastebin.com/eAhEHssQ
http://stackoverflow.com/questions/7038636/how-to-change-the-marker-for-the-overlay-on-tap-for-android
2012年8月15日 星期三
使用try偵測EditText的值是否為數字
如果我想偵測某個EditText是否為全部數字且要在0~100間的話要怎麼做呢?設定EditText輸入的格式後,當然我知道大家都會說這很簡單阿,但分享一下我覺得很聰明的方式。
如果輸入的不是數字,那麼在Double.parseDouble時會錯誤,則會跳到catch 去顯示Dialog,不符合0~100時,也會到catch 去顯示Dialog,這樣程式碼真簡潔。
try顯示的Dialog的方法
{
first_rate = Double.parseDouble(rate1.getText().toString());
if (first_rate < 0 || first_rate > 100)
{
throw new Exception();
}
}
catch (Exception ex)
{
ShowDialog("錯誤","格式錯誤, 請輸入 0 ~ 100 之間的數字");
}
private void ShowDialog(String title,String msg)
{
AlertDialog.Builder builder = new Builder(getActivity());
builder.setTitle(title);
builder.setMessage(msg);
builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
Dialog noticeDialog = builder.create();
noticeDialog.show();
}
2012年8月12日 星期日
Java單例模式(可以減少Andoroid記憶體使用量)
如果有個類別常常使用,那要使用時都必須再new出一個類別,但如果一龐大起來,也許會造成資源不必要的浪費,或許善用static是一個方法,如下:
後續還有一堆很深的意義可以去思考,例如假設有個需求,假設某些資源取得頻繁時,我們可以去定義一個靜態的Map當作資料快取,要取得資料時:
看完王者歸來-品味 Java 的 21 種設計模式後,自己紀錄的心得。
public class Singleton { //3.建立一個靜態的類別,直接在這邊建立只會一次。 private static Singleton instance=new Singleton(); //1.私有化建構方法,這樣就不能new出本類別。 private Singleton(){ } //2.定義一個方法堤供用戶端產生好的實例 public static Singleton getInstance(){ return instance; } public int getCount(int x,int y){ return x+y; } }
public class Client { /** * @param args */ public static void main(String[] args) { Singleton aa=Singleton.getInstance(); System.out.println(aa.toString()); Singleton bb=Singleton.getInstance(); System.out.println(bb.toString()); System.out.println(aa.getCount(5, 5)); } }這樣一來,你會發現System.out.println(aa.toString())跟bb時,他們的記憶體位置是一樣的,這樣能夠有效減少記憶體使用量。
後續還有一堆很深的意義可以去思考,例如假設有個需求,假設某些資源取得頻繁時,我們可以去定義一個靜態的Map當作資料快取,要取得資料時:
(1)檢查map記憶體位置中是否有資料,如果有直接使用map記憶體裡面得資料值。
(2)如果記憶體位置中沒有值,我們可以從服務器或sqlite去取得資料,取得完後再存入map記憶體中以便下次使用。
這讓我想到在Android上使用google map時,一移動地圖就要從服務器撈取大量座標要標註在地圖上的時候,是不是也能夠使用此邏輯去增加再次顯示的速度?
看完王者歸來-品味 Java 的 21 種設計模式後,自己紀錄的心得。
2012年7月29日 星期日
不重複開啟Activity的方法
在有好多Activity中,Intent過來又intent過去常常會開好多重複的Activity,今天我發現了很好用的方法,就是加上以下這行
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
這樣就可以激活OnStop狀態的Activity囉
2012年7月20日 星期五
Android 保持螢幕清醒不休眠
Android 禁止系統休眠,使屏幕不變暗,保持遊戲中屏幕高亮
實現這一功能的方法有兩種,一種是在Manifest.xml文件裡面聲明,一種是在代碼裡面修改LayoutParams的標誌位。具體如下:
1、在Manifest.xml文件裡面用user-permission聲明。代碼如下:
1、在Manifest.xml文件裡面用user-permission聲明。代碼如下:
- <uses-permission android:name="android.permission.WAKE_LOCK">
- </uses-permission>
這種方法,在安裝apk時,系統會提示安裝人是否允許使用禁止休眠功能。
2、在程序中用代碼實現。代碼如下:
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
把這段代碼加在setContentView(R.layout.main)之前即可
這種方法,安裝時,不會提示安裝人是否允許使用禁止休眠功能
2012年6月3日 星期日
在ListView中使用CheckBox
在ListView上如果加入Checkbox,在滑動時會發現明明只有打勾一個,下滑時卻有好多個被打勾,這時就必須使用BaseAdapter這個類別來自定ListView,先來釐清幾個重點再看範例會比較清楚。
最後附上源碼,包含ListView點擊後變色。
點左上角File的Download就可以下載
下載
//創建一個類別專門用來記錄每一列checkbox的狀態 class check_msg { boolean ischeck; public check_msg(boolean ischeck,String text){ this.ischeck=ischeck; } }
//宣告一個list陣列儲存的是check_msg 這個列別的狀態 ArrayListlist2 = new ArrayList ();
//用一個迴圈設定每一列的check初始狀態 list2.add(new check_msg(false));
//當checkbox狀態被點擊時變更狀態。 final check_msg msg = list2.get(arg0); viewHolder.cb1.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub msg.ischeck=!msg.ischeck; } });
最後附上源碼,包含ListView點擊後變色。
點左上角File的Download就可以下載
下載
2012年5月12日 星期六
在Fragment使用DialogFragments
今天在http://android-developers.blogspot.com/2012/05/using-dialogfragments.html上看到使用DialogFragments才知道原來要在fragment的畫面上呈現一個Dialog這麼簡單,但網路上可以查到的資料好像還是相當少,附上簡單的實作DialogFragments連結,一看就懂了。
先附上官網的效果圖...
點左上角File的Download就可以下載囉
DialogFragments範例下載
先附上官網的效果圖...
點左上角File的Download就可以下載囉
DialogFragments範例下載
2012年5月4日 星期五
Android Sqlite 開關問題
一直以來使用Sqlite開關方面,一直出現問題譬如以下錯誤畫面
05-04 14:14:50.870: E/AndroidRuntime(7173): java.lang.IllegalStateException: database /data/data/etwarm.namespace/databases/Super_data.db (conn# 0) already closed
或
close() was never explicitly called on database
等等等...........
這類的錯誤(close訊息)都只是上個db沒有關閉又開了一次,譬如開了一次getReadableDatabase()又再開了一次getReadableDatabase(),這樣在DDMS就會看到錯誤訊息,雖然不至於影響整個應用程序,但看到錯誤訊息心理就不是很舒服。
個人在程序上的方式如下,自己筆記一下。
//這個應用程序有使用2個db,先在最上頭宣告為null值 private DBOpenHelper dbHelper=null; private Customer_DBOpenHelper customer_dbHelper=null; SQLiteDatabase db=null; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //宣告 dbHelper = new DBOpenHelper(this); customer_dbHelper = new Customer_DBOpenHelper(this); } //使用2個public,當dbHelper開時,customer_dbHelper就關,customer_dbHelper要開時dbHelper就關 public void db_help_open(){ if(customer_dbHelper!=null){customer_dbHelper.close();} db = dbHelper.getReadableDatabase(); } public void customer_db_help_open(){ if(dbHelper!=null){dbHelper.close();} db = customer_dbHelper.getReadableDatabase(); } //當離開畫面時呼叫all_cursor_db_close()這個自己寫的方法 public void onPause() { // TODO Auto-generated method stub all_cursor_db_close(); super.onPause(); } //把他全部關閉 public void all_cursor_db_close(){ if(cursor!=null){cursor=null;} if(customer_dbHelper != null){customer_dbHelper.close();} if(dbHelper != null){dbHelper.close();} }如果各位有更好的做法及建議,歡迎各位共同討論!!
2012年5月1日 星期二
Index -1 requested, with a size of 1的問題原因
今天在使用Sqlite的cursor時出現以下錯誤訊息
05-02 02:54:56.928: E/AndroidRuntime(1660): android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
再來看一下官方文件
public abstract int getColumnIndex (String columnName)
Since: API Level 1
Returns the zero-based index for the given column name, or -1 if the column doesn't exist. If you expect the column to exist use
getColumnIndexOrThrow(String)
instead, which will make the error more clear.if(cursor.getCount()>0) { while(cursor.moveToNext()) { String test=cursor.getString(cursor.getColumnIndex("customer_want")); Log.i("Tag","這是cursor取得的值:"+test.toString()); } }
2012年4月30日 星期一
Failure delivering result ResultInfo問題原因
使用返回按鍵回上個Activity時遇到了以下錯誤。
Failure delivering result ResultInfo{who=android:fragment:2, request=0, result=0, data=null} to activity {etwarm.namespace/etwarm.buy.fragment.buy_home_main}: java.lang.NullPointerException
我們從錯誤訊息可以觀察到data=null所以錯誤了,那data在哪呢?其實就是返回的那個Activity有使用到onActivityResult,只要判斷一下data這個是否為空即可,如if(data!=null ),請參考以下。
public void onActivityResult(int requestCode, int resultCode, Intent data) { //把勾選要自訂的物件回傳 super.onActivityResult(requestCode, resultCode, data); if(data!=null ){ if(requestCode == SELECT_OJ_CODE) { String select_oj_id=data.getStringExtra("SELECT_OJ"); if(!select_oj_id.equals("")){ Log.i("Tag", select_oj_id.toString()); dao.update_want(table_name, test_tmp, select_oj_id); } } } }
2012年4月25日 星期三
cannot be cast to android.widget.錯誤
今天很簡單的只是把checkbox調到textview的前面卻出現以下問題。
04-25 15:49:03.441: E/AndroidRuntime(15710): java.lang.ClassCastException: android.widget.TextView cannot be cast to android.widget.CheckBox
解決方式很令人意外的重新命名checkbox的id後又好了,真是奇怪。
04-25 15:49:03.441: E/AndroidRuntime(15710): java.lang.ClassCastException: android.widget.TextView cannot be cast to android.widget.CheckBox
解決方式很令人意外的重新命名checkbox的id後又好了,真是奇怪。
2012年4月23日 星期一
JDOM搭配HttpClient Post
今天要把Android上的某字串以XML的方式POST給Server,使用了JDOM(要先下載\並匯入.jar檔)將訊息建立成XML格式後存入字串變數,再以Post的方式給Server,如以下:
package com.fff; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.output.XMLOutputter; import android.app.Activity; import android.os.Bundle; import android.util.Log; public class JOM_POST_Test1Activity extends Activity { /** Called when the activity is first created. */ String aa=""; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { BuildXMLDoc(); } catch (Exception e) { e.printStackTrace(); } final String TAG = "ApacheHttpClientTest"; String response = ""; String url = "http://10.40.204.137:8080/project/test"; Listparams = new ArrayList (); params.add(new BasicNameValuePair("id",aa)); params.add(new BasicNameValuePair("name","kuka")); try { response = httpPost(url, params); } catch (Exception e) { e.printStackTrace(); } Log.i(TAG, "####"+response); } public void BuildXMLDoc() throws IOException, JDOMException { List list = new ArrayList (); List list2 = new ArrayList (); list.add(0, "1111111111"); list2.add(0, "11,22,33,44,55"); list.add(1, "2222222222"); list2.add(1, "11,22,33,44,55"); list.add(2, "3333333333"); list2.add(2, "11,22,33,44,55"); Element root = new Element("list"); Document Doc = new Document(root); Element elements; XMLOutputter outputter = new XMLOutputter(); for(小於list容量時) { elements= new Element("user"); elements.setAttribute("id", "" + i); elements.addContent(new Element("_id").setText(list.get(i))); elements.addContent(new Element("oj_want").setText(list2.get(i))); root.addContent(elements); aa+= outputter.outputString(elements); } System.out.println(aa); /* //如要產生XML的檔案使用以下 XMLOutputter XMLOut = new XMLOutputter(); XMLOut.output(Doc, new FileOutputStream("user.xml")); */ } public String httpPost(String url, List params) throws Exception { String response = null; HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(url); try { httppost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8)); HttpResponse httpResponse = httpclient.execute(httppost); int statusCode = httpResponse.getStatusLine().getStatusCode(); if(statusCode==HttpStatus.SC_OK) { response = EntityUtils.toString(httpResponse.getEntity()); } else { response = "錯誤"+statusCode; } }catch (Exception e) { e.printStackTrace(); } return response; } }
2012年4月18日 星期三
使用addTextChangedListener偵測EditTex
今天想做個Edittext輸入自動搜尋,原本使用setOnKeyListener的時候,輸入中文都要再按一次完成才會即時才會擷取,結果發現addTextChangedListener更好用呢,一輸入就即時更新字串,跟WhatsApp的搜尋聯絡人一樣,很即時搜尋唷。
package comfff.fff; import android.app.Activity; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.KeyEvent; import android.view.View; import android.widget.EditText; import android.widget.TextView; public class Test_setOnKeyActivity extends Activity { /** Called when the activity is first created. */ private EditText myEditText01; private TextView myTextView01; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myEditText01 = (EditText)findViewById(R.id.EditText01); myTextView01 = (TextView)findViewById(R.id.TextView01); myEditText01.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { System.out.println("beforeTextChanged"); // TODO Auto-generated method stub } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub System.out.println("onTextChanged"); if(myEditText01.getText().length()==0) { myTextView01.setText("空白"); } else{ myTextView01.setText(myEditText01.getText()); } } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub System.out.println("afterTextChanged"); } }); } }
2012年4月16日 星期一
在Android 使用Sqlite注意事項
近來使用Sqlite時一直遇到很多挫折,所以將這些問題紀錄下來,防止下次出現相同錯誤。
- 在Fragment中如果要傳入this(getActivity())這個參數時,一定要在onActivityCreated之後,不然一定出現 NullPointerException,這個問題很簡單卻困擾了我一天。
- 如果在這個Activity中有使用到cursor,可以在最上層定義Cursor curosr=null,然後在Activity進入onPause() 時定義關閉,例如: if(cursor!=null){cursor.close();},然後在關閉db,例如: if(db!=null){db.close();}
2012年4月10日 星期二
檢查sqlite中某個資料表是否存在
有兩種方法,
第一種方法是:不需要知道表是否存在,在創建表的時候加上if not exists 例:create table if not exists myTable(...) ,這樣做的好處是,不需要知道表是否存在,只要每次都進行創建即可。因為裡面有判斷,如果表存在的時候,再執行這句不會發生重複創建表的情況。
第二種方法是:直接執行某個SQL語句,用try...catch來捕獲數據庫操作的異常。當異常表示數據庫表不存在的時候,再進行處理。例:
try{
Cursor c = getWritableDatabase().query("select * from myTable",null );
catch(Exception e) // 或者是 SQLiteException .
{//添加處理代碼,例如:創建表。
}
第二種的方法不如第一種好,原因是:第二種寫起來比較麻煩,還有,如果有其它異常的時候,需要對異常來進行判別,並處理。
PS:
上面的E文中有一種方法是判斷query的返回值 ,那個別想了,我在測試的時候,如果表被刪除了,一到那裡就崩潰,只能通過try...catch的方法。
2012年4月1日 星期日
從Fragment中取得main Activity中的值
今天遇到了一個狀況,就是Intent時傳遞了一個字串參數到了一個Fragment的main頁面,但是想要把這個intent過來的時傳遞到左側的fragment中,看書知道可以用callback看又覺得超困難,所以其實可以用一個很簡單的方法就是
假設現在的狀況是
1.fragment主畫面:buy_main
2.左側fragment:fragment_list
3.右側fragment:fragment_text
左側想取得main中的值可以宣告一個方法,如想取得bundle_msg_id值這個參數,以下
public String get_bundle_msg() { return this.bundle_msg_id; }
然後在左側fragment:fragment_list中使用getActivity()取出main中的參數
String bundle_msg_id=((buy_main)getActivity()).get_bundle_msg();
訂閱:
文章 (Atom)
星期、月份英文縮寫
中文 英文 3字母 縮寫 3字母 縮寫 2字母 縮寫 2字母 縮寫 1字母 縮寫 1字母 縮寫 其他 縮寫 星期日 Sunday SUN Sun SU Su S S 星期一 Monday MON Mon MO Mo M M 星期二 Tuesday TUE Tue TU ...
-
今天想做個Edittext輸入自動搜尋,原本使用setOnKeyListener的時候,輸入中文都要再按一次完成才會即時才會擷取,結果發現 addTextChangedListener 更好用呢,一輸入就即時更新字串,跟WhatsApp的搜尋聯絡人一樣,很即時搜尋唷。 ...
-
要把經緯度店址可以使用以下作法 Geocoder gc = new Geocoder(getActivity(), Locale.TRADITIONAL_CHINESE); List<Address> lstAddress = gc.getFromLocation...
-
中文 英文 3字母 縮寫 3字母 縮寫 2字母 縮寫 2字母 縮寫 1字母 縮寫 1字母 縮寫 其他 縮寫 星期日 Sunday SUN Sun SU Su S S 星期一 Monday MON Mon MO Mo M M 星期二 Tuesday TUE Tue TU ...