參照連接這裏解決。緣由是as沒法識別BOM的問題。人生中第一次遇到這個問題是大學時寫PHP,那時候就緊緊的記住個了。時隔這麼多年,在另外一款編輯器另外一種語言中又遇到了,緣分啊!html
這裏 (如出一轍的內容) 有關於AlertDialog的基本使用,基本能夠參考到了。不過更好的是如何與AlertDialog交互的問題,有一篇文章寫得特別好,可是找不到了。java
在onClick(DialogInterface,int,int which)中,能夠經過DialogInterface的getId來區分彈出的AlertDialog,按鍵則經過which了。這種狀況適合於將全部的AlterDialog的onClick回調所有綁定到自身的狀況了。android
這裏ListView使用的文章,而這個是關於android.R.layout裏面定義的與listview有關的那部分xml說明,值得參考。這個詳細的介紹了adapter狀況,值得回味一下git
簡書中的這篇文章簡單卻頗有效的介紹了BaseAdapter的用法,比其餘的更加有效,看完以後就基本瞭解了其原理及應用github
這裏是有關android自帶的系統圖標,能夠經過android.R.drawable/訪問,至少用做臨時的place holder也能夠嘛!sql
這裏有關Activity.this與this區別。寫過js因此的對於閉包有些懼怕,但在這裏因而乎仍是一目瞭然。數據庫
fab_save.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mOptStatus = OperationStatus.Other; if (mArea.getCount() == 0) { Toast.makeText(MainApplication.getContext(), "請先圈定範圍", Toast.LENGTH_SHORT).show(); } else { View vv = LayoutInflater.from(MainApplication.getContext()).inflate(R.layout.save_line_dialog, null); save_name_et = (EditText) vv.findViewById(R.id.save_line_et); save_line_ad = new AlertDialog.Builder(getActivity()) .setTitle("輸入名稱") .setView(vv) .setPositiveButton("保存", iActivity.this) .setNegativeButton("取消", null).create(); save_line_ad.show(); } } });
這裏表述了這二者(LongClick和Click)的過程。默認狀況下as自動生成的代碼模板,LongClick是返回false。若是想本身觸發,則須要手動改爲true.編程
@Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { mItem_index=position; del_prj_ad.show(); return true; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mItem_index=position; open_prj_ad.show(); }
/*json
* 好吧,後來發現即便長按,也沒有彈出Dialog,非常奇怪啊,segmentfault
* 仔細查看後發現是沒有註冊onItemLongClick,很差意思,可是應該仍是有關係的,
* 要否則總會瞎onItemClick的。
*/
這裏還有一個對Button或者ImageButton長按的說明,道理類似。
這個問題只有去訪問該項目的github,不過看完以後仍是會驚歎,果真是沒有。它自己不打算考慮像ArrayList那樣能夠add到任意的index(雖然它內部的實現仍是使用ArrayList),而經過put(Object o)方法就是將o放到內部List的尾部(直接List.add(o)),而put(index,o)是更改內部index位置的對象,不是想象的add(index,o)的實現。好了,想insert的想法是不能有的。
能夠考慮新建對象,可是,開銷太大了點,不值得。
使用泛型,確實是使用java的ArrayList<E>,可是知道這個(或者類似概念)要算是學習C++時涉及到的模板(template)。segmentF的講解和排版都不錯,是個入門的教程。提到的《java編程思想》也確實值得學習。這個的例子仍是蠻多。
講真,能想到用泛型的,估計都是手懶到必定程度了吧。我怎麼想到用泛型了呢?不一樣的類型,卻面對着相同的操做。即便是實現了相同的接口,卻也沒法將類型傳遞進去,承受着這種手忙腳亂的感受,忽然唸叨了Python的好。
public JSONArray returnResult(ArrayList<IInterface> ii) { JSONArray a=new JSONArray(); for(IInterface i:ii) { a.put(i.toJson());//看着也能夠呀,忘記了不行的寫法了 } return a; }
這個事情很煩躁啊,也多是沒認真研究的緣故。這裏講了動態與靜態(即xml文件)處理frgment的問題,誰知道是否是坑呢。而這個研究的很細緻了,將每個過程(onCreate,onStart等等)說的很清楚,排版不錯呦。
這裏算是簡介,而這裏講的很是透徹,固然在我還沒弄清除以前還不能寫太多評論。個人代碼有些卡頓了。不知爲什麼。慢慢的調試中。
int vol_id=0x01; int salt_id=0x02; int space_id=0x03; Handler mHandler=new Handler(new Handler.Callback(){ @Override public boolean handleMessage(Message msg) { Log.i("E","xxxxxx"+ msg.what); if(msg.what==vol_id) if(vol_tv!=null) { vol_tv.setText(vol_tv_text); } else if(msg.what==salt_id) if(salt_tv!=null) { salt_tv.setText(salt_tv_text); } else if(msg.what==space_id) if(space_tv!=null) { space_tv.setText(space_tv_text); } return false; } });
網絡上能搜索到的關於設置和獲取TextView的代碼不少,除了有關於考慮android版本狀況的,其餘的幾乎是一致的。
然而本身的代碼確實是總返回null,調試中能夠看到mColor爲空。在代碼中,本身的空間是從xml佈局中直接獲取的,雖然在xml的父container中設置了backgroud,可是經過findViewById得到的仍是努力了。最後不得不先嚐試,即在findViewById以後手動調用setBackgroundColor,這樣再次獲取時就成功了。
Stack overflow中的這篇問題中的答案解析比較全面,但仍是沒說個人這種狀況。
自我感受,這種方式的初始化應該會用得更多,因此記錄下來,直接copy就能夠了。其中包括了數據庫路徑優先外置存儲器選擇,適當改改也能夠進行單利化。
public class PathDatabase extends SQLiteOpenHelper { public static int version=1; public static String db_name="name.db"; String table_name="table"; SQLiteDatabase mSQLiteDatabase; private PathDatabase(Context c,String full_db_name){ super(c,full_db_name,null,PathDatabase.version); } public static PathDatabase getInstance(Context c){ if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)&&Environment.isExternalStorageEmulated()) { return new PathDatabase(c,Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+db_name); }else { return new PathDatabase(c,db_name); } }
關於sqlite得到id的問題,insert方法確實能夠得到插入數據的rowid,文檔上就這麼寫的。
public long insert (String table, String nullColumnHack, ContentValues values)
Added in API level 1
Convenience method for inserting a row into the database.
Parameters
table the table to insert the row into nullColumnHack optional; may be null
. SQL doesn't allow inserting a completely empty row without naming at least one column name. If your providedvalues
is empty, no column names are known and an empty row can't be inserted. If not set to null, thenullColumnHack
parameter provides the name of nullable column name to explicitly insert a NULL into in the case where yourvalues
is empty.values this map contains the initial column values for the row. The keys should be the column names and the values the column values Returns
- the row ID of the newly inserted row, or -1 if an error occurred
可是呢,又有提出,使用rowid做爲主鍵是很不安全的,由於rowid會更改,作法就是
If you don’t want to read the whole post then just do this: Everytime you create a table with sqlite make sure to have an INTEGER PRIMARY KEY AUTOINCREMENT column (the rowid column will be an alias to this one).
因此我考慮就這麼定義吧,希望insert的時候返回的是這貨。
對於現現在的系統,Activity中有處理按返回鍵的事件,public void onBackPressed(),固然自動生成的會有super方法,也就會觸發退出事件,通常會直接改掉。這個是具體的介紹,而這個介紹了雙擊退出鍵退出程序的寫法,無非就是用時間差,簡單而高效有用。我還想到用2秒自毀線程,而後在主線程中判斷是否運行,實際上會挺犯不上的。
Simple is better than complex
public class Common { public static long last_time_click=-1; public static int backclick_internal=2; } @Override public void onBackPressed() { if((System.currentTimeMillis()-Common.last_time_click)<Common.backclick_internal){ finish(); System.exit(0); }else{ Common.last_time_click=System.currentTimeMillis(); } }
動態更改是經過LinearLayout.LayoutParams來更改,調用View.setLayoutParams,好比這裏說的清楚。可是遇到兩個事情:java.lang.ClassCastException和寬度問題。
CastException問題是在給View的時候,可是這裏的param應該是其父容器的類型,即在轉換的時候(View.getLayoutParam獲取的是ViewGroup.LayoutParams對象,須要強制轉換)給出正確的類型。這裏說明了一下,確實很準確。
RelativeLayout.LayoutParams mLayoutParams; public void onClick(View v) { mLayoutParams=(RelativeLayout.LayoutParams)mView.getLayoutParams(); if(mImageButton1.isSelected()){ mImageButton1.setSelected(false); mLayoutParams.width= Util.dip2px(Util.change_map_type_short_width); }else{ mImageButton1.setSelected(true); mLayoutParams.width=Util.dip2px(Util.change_map_type_long_width); } mView.setLayoutParams(mLayoutParams); }
寬度是由於在代碼中賦值給width是像素值,而多數狀況下是dip的數值,這須要進行轉換計算。這裏給了代碼,可是感受通用性不強,因而本身改造了Application類,見(十五)。經過靜態方法,將計算的scale值放在第一次運行時計算。
public class Util { public static int px2dip(float pxValue) { return (int) (pxValue / MyApplication.scale + 0.5f); } public static int dip2px(float dpValue) { return (int) (dpValue * MyApplication.scale+0.5f); } }
這種方式是最爲方便的,雖然沒有顧忌太多的。這裏是博客,下面是根據本身須要改造後配合上面計算像素與dip轉換。
public class MyApplication extends Application { private static Context context; @Override public void onCreate() { super.onCreate(); context=getApplicationContext(); scale=context.getResources().getDisplayMetrics().density; } public static Context getContext() { return context; } public static float scale ; }
經過服務獲取便可,惟一的就是幾個參數:一個是使用一個毫秒數來震動多久,另外一個是兩個參數,前一個是long數組,兩兩結合表示停頓時間,震動時間,第二個參數表示循環起始下標,若是使用-1則表示震動一次。具體的參看這裏或者這裏。代碼抄至後者。
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); vibrator.vibrate(2000);//震動指定時間 ,數據類型long,單位爲毫秒,一毫秒爲1/1000秒 vibrator.vibrate(new long[]{100,10,100,1000}, -1);//按照指定的模式去震動。 vibrator.cancel();//取消震動,當即中止震動。震動爲一直震動的話,若是不取消震動,就算退出,也會一直震動
這個很基礎,只惋惜沒注意過,或者沒有學過。應爲List以及ArrayList中只能存放繼承至Object的對象,對於值類型不支持,可是可使用其封裝爲Object的Integer以及相似的對象,好比這裏說明的意思。
本來我使用的方法是下面。
public static Database getInstance(Context c){ if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)&&Environment.isExternalStorageEmulated()) { return new PathDatabase(c,Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+db_name); }else { return new Database(c,db_name); } }
可是發現,儲存卡與sdcard的關係不必定,有多是sdcard1纔是儲存卡因此須要一個準確的獲取方法。
這裏講的很是全面。以前一直使用其餘寫法。原理之後能夠詳看(主要是Java的反射機制),下面代碼就抄過來了。這個寫的也不錯,可是內容也差很少,作補充。
import java.lang.reflect.Method; import android.os.storage.StorageManager; // 獲取主存儲卡路徑 public String getPrimaryStoragePath() { try { StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE); Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths", null); String[] paths = (String[]) getVolumePathsMethod.invoke(sm, null); // first element in paths[] is primary storage path return paths[0]; } catch (Exception e) { Log.e(TAG, "getPrimaryStoragePath() failed", e); } return null; } // 獲取次存儲卡路徑,通常就是外置 TF 卡了. 不過也有多是 USB OTG 設備... // 其實只要判斷第二章卡在掛載狀態,就能夠用了. public String getSecondaryStoragePath() { try { StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE); Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths", null); String[] paths = (String[]) getVolumePathsMethod.invoke(sm, null); // second element in paths[] is secondary storage path return paths.length <= 1 ? null : paths[1]; } catch (Exception e) { Log.e(TAG, "getSecondaryStoragePath() failed", e); } return null; } // 獲取存儲卡的掛載狀態. path 參數傳入上兩個方法獲得的路徑 public String getStorageState(String path) { try { StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE); Method getVolumeStateMethod = StorageManager.class.getMethod("getVolumeState", new Class[] {String.class}); String state = (String) getVolumeStateMethod.invoke(sm, path); return state; } catch (Exception e) { Log.e(TAG, "getStorageState() failed", e); } return null; }