android 編程小技巧(持續中)
first:
Intent跳轉一般存用於Activity類,但是若要在非activity類裡跳轉的話,解決方法是在startActivity(intent)前加mContext即上下文,最終為:mContext.startActivity(intent); 換言之,以後在非activity類裡調用activity的方法 一律這麼做。若不行的話 可以這麼做:(Activity)mContext。
second:
gridview中textview內容不能居中的問題。gridview中可以設置一行顯示多少個item,所以他為每個item都預留了一部分空間。若用textview來填充item 而textview的屬性又為wrap_content時,因為內容較少,只占據了分配空間的一部分,所以無論怎麼去調試屬性,看上去都像是頂格顯示;故解決方法是讓textview的寬度為marth_parent,這樣grity = "centre"才會有:-D。
third:
Scrollview下面只能嵌套一個控件,當有多個控件時可以在Scrollview裡套上一個Relativelayout 就可以就解決問題。
forth:
Android SDK Content load很慢解決方法 在C:\Documents and Settings\計算機名 這個路徑下有個.android文件夾, 把這個文件夾刪了 然後重啟模擬器 會彈出一個對話框 Welcome to Android Development 選擇NO就可以了
five:
在多層嵌套時 若層數過多會出現 明明控件的visibilty是visible 但在界面上仍是不可見的情況 貌似相當的詭異 解決方法:多個布局換著用 不要一直用linearlayout 可以套一個relativelayout。原因不明
six:
若activity裡的某些響應時基於adapter數據的 而adapter又與activity分開 使得數據無法回傳到activity(具體見Listview與GridView預留數據接口一文) 解決方法如下:
一般來說adapter是由activity調用的 需要傳入activity的activity listdata等等信息 所以 我們在就收數據時 把activity方法得到 見代碼:
QYSPActivity activty; //調用這個adapter的activity類
public QYSPFLInfoAdapter(Activity activity, List
listdata) {
super(activity, 0, listdata);
activty = (QYSPActivity) activity; // 獲取activity的類
}
在需要的地方調用activity裡的方法
activty.doPost(XXXXX); //doPost()是在activity裡定義好的方法 public
記住了 取名字的時候不要取activity因為這個名字與(QYSPActivity)activity一樣,然後獲得的activity方法就是空的 然後 然後 各種error 解決方法 換名字或者 this.activity =(QYSPActivity) activity; 說白了 就是this. 語句 傷不起~~
目測這個方法可以舉一反三 但是怎麼反 待定。。。
seven:
setContentView和inflate區別 setContentView()一旦調用, layout就會立刻顯示UI;而inflate只會把Layout形成一個以view類實現成的對象,有需要時再用setContentView(view)顯示出來 .一般在activity中通過setContentView()將界面顯示出來,但是如果在非activity中如何對控件布局設置操作了,這需LayoutInflater動態加載
eight:
動態刪除listview的item
nine:
使用contentView+靜態類ViewHolder類來優化adapter 當我們判斷convertView==null的時候,如果為空,就會根據設計好的List的Item布局(XML),來為convertView賦值,並生成一個viewHolder來綁定converView裡面的各個View控件(XML布局裡面的那些控件)。再用convertView的setTag將viewHolder設置到Tag中,以便系統第二次繪制ListView時從Tag中取出。(看下面代碼中)
ViewHolder holder;
if(convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item, null);
holder.img = (ImageView)convertView.findViewById(R.id.img);
holder.title = (TextView)convertView.findViewById(R.id.title);
holder.info = (TextView)convertView.findViewById(R.id.info);
convertView.setTag(holder);
}else
{
holder = (ViewHolder)convertView.getTag();
holder.img.setImageResource(R.drawable.ic_launcher);
holder.title.setText("loulijun");
holder.info.setText("www.cnblogs.com/loulijun");
}
eleven: 單個控件的xml不能放縮問題
其實這裡不管你將Button的layout_width和layout_height的值修改成多少,都不會有任何效果的,因為這兩個值現在已經完全失去了作用。平時我們經常使用layout_width和layout_height來設置View的大小,並且一直都能正常工作,就好像這兩個屬性確實是用於設置View的大小的。而實際上則不然,它們其實是用於設置View在布局中的大小的,也就是說,首先View必須存在於一個布局中,之後如果將layout_width設置成match_parent表示讓View的寬度填充滿布局,如果設置成wrap_content表示讓View的寬度剛好可以包含其內容,如果設置成具體的數值則View的寬度會變成相應的數值。這也是為什麼這兩個屬性叫作layout_width和layout_height,而不是width和height。
再來看一下我們的button_layout.xml吧,很明顯Button這個控件目前不存在於任何布局當中,所以layout_width和layout_height這兩個屬性理所當然沒有任何作用。那麼怎樣修改才能讓按鈕的大小改變呢?解決方法其實有很多種,最簡單的方式就是在Button的外面再嵌套一層布局. 當然這個時候最外層的布局失去作用了。
ten:throw與throws的區別
throw語句用在方法體內,表示拋出異常,由方法體內的語句處理
throws語句用在方法聲明後面,表示再拋出異常,由調用這個方法的上一級方法中的語句來處理
throws主要是聲明這個方法會拋出這種類型的異常,使其他地方調用它時知道要捕獲這個異常。
throw是具體向外拋異常的動作,所以它是拋出一個異常實例。
throws說明你有哪個可能,傾向
throw的話,那就是你把那個傾向變成真實的了同時:
1)throws出現在方法函數頭;而throw出現在函數體;
2)throws表示出現異常的一種可能性,並不一定會發生這些異常;throw則是拋出了異常,執行throw則一定拋出了某種異常;
3)兩者都是消極處理異常的方式(這裡的消極並不是說這種方式不好),只是拋出或者可能拋出異常,但是不會由函數去處理異常,真正的處理異常由函數的上層調用處理。
twelve:gravity與 layout_gravity
android:gravity:是對view控件本身來說的,是用來設置view本身的文本應該顯示在view的什麼位置,默認值是左側
android:layout_gravity:是相對於包含改元素的父元素來說的,設置該元素在父元素的什麼位置
對於LinearLayout如果設置android:orientation="vertical",那麼android:layout_gravity的設置只在水平方向生效;如果設置android:orientation="horizontal",那麼android:layout_gravity屬性只在垂直方向生效。
thirteen:帶刪除按鈕及功能的輸入框
* 因為我們不能直接給EditText設置點擊事件,所以我們用記住我們按下的位置來模擬點擊事件
* 當我們按下的位置 在 EditText的寬度 - 圖標到控件右邊的間距 - 圖標的寬度 和
* EditText的寬度 - 圖標到控件右邊的間距之間我們就算點擊了圖標,豎直方向沒有考慮
這三行話 是關鍵。
代碼如下:
boolean touchable = event.getX() > (getWidth()
- getPaddingRight() - mClearDrawable.getIntrinsicWidth())
&& (event.getX() < ((getWidth() - getPaddingRight())));//mClearDrawable為刪除按鈕
if (touchable) {
this.setText("");
}
在輸入框中添加刪除按鈕
forteen:open failed: EISDIR (Is a directory)
在SD卡中創建目錄文件夾的時候,應該一層一層的創建文件夾,但是不能一次同時創建這兩個文件夾.容易把具體創建的文件當作要創建的空文件夾來創建。將"/mnt/sdcard/zhufu/apkbus.db"當作文件夾來創建,這樣就會出現EISDIR錯誤,解決方法:先創建前面的文件夾,在創建最終文件。
如:File parentFile = new File(path);
if (!parentFile.exists()) {
parentFile.mkdirs();
}
File file = new File(parentFile, filename + ".jpg");//這就是最終存放位置,在這裡千萬不能重復madirs,否則就會出現上面的錯誤。
15:播放同一個文件MediaPlayer報IO異常
解決方法:能夠播放一次說明Player及文件都是沒有問題的,但是如果播第二次 有時候或報IO異常,原因是待播放的文件正在被占用,若要正常播放的話必須在Player使用它之前,這個資源是被 release的。player.release(); 。
16:scrollview默認初始位置在頂部
因為scrollView裡面ListView的上面還有其他的控件,所以我想到一個辦法就是使得一開始的時候就讓上面其中一個控件獲得焦點,滾動條自然就到頂部去了,如下:
txtBaseMsg.setFocusable(true);
txtBaseMsg.setFocusableInTouchMode(true);
txtBaseMsg.requestFocus();
控制其滑動到底部: sv.fullScroll(ScrollView.FOCUS_DOWN);
17:Notification 動態圖標
一般默認notification的圖標是靜態的,但是在某些情況下 圖標需要是動態的,解決方法其實蠻簡單 就是給notification不停的換icon,然後就顯示出來。
notif.iconLevel = 0;
manager.notify(0, notif);
SystemClock.sleep(100);
notif.iconLevel = 1;
manager.notify(0, notif);
18:getWidth和getMeasuredWidth區別
getWidth(): View在設定好布局後,整個View的寬度
getMeasuredWidth():對View上的內容進行測量後得到的View內容占據的寬度。前提是你必須在父布局的onLayout()方法或者此View的onDraw()方法裡調用measure(0,0);(measure參數的值可以知己定義),否則得到的結果和getWidth()得到的結果是一樣的。
這兩個方法最主要的區別在於,是否使用了measure()方法,同時measure()使用的位置也很重要。
getHeight() 和 get MeasuredHeight() 區別同理。
geiHeight有時候會得到0,一般原因是在View還未繪制完之前調用這個方法,所以得到的就是0。解決該問題的方法有很多,主要就是延後調用這些方法。可以試著在onWindowFocusChanged()裡面調用這些方法。
19:onItemClickListener點擊區分
多個listView或GridView都要獲得item的點擊監聽時,一般都是直接調用系統的onItemClickListener接口,但是他們並不能區分開來,而且得不到id,不能像ClickListener一樣用v.getId來區分,但是可以利用parent的get來區分,他就相當於clickListener的view一樣。
20:在文字下面圖片(代碼版)
//獲得圖片資源及大小 最後兩句為銷毀圖片 防止OOM
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.icon_daohang_select);
width = bitmap.getWidth();
height = bitmap.getHeight();
bitmap.recycle();
bitmap = null;
重點來了:
holder.text1.setText(mTextList.get(position));
Drawable d = mContext.getResources().getDrawable(mImgList.get(position));
d.setBounds(0, 0, width, height);
holder.text1.setCompoundDrawables(null, d, null, null);
21:關於在xml裡 android:onClick="onClick"的巧妙用法
在代碼裡若引入了其他地方的xml那麼xml的點擊事件就有一點麻煩,所以可以采用之前題目的那個方法,因為這個和android自帶的onclick事件相同,所以可以直接套用點擊方法。(其他部分與普通onclick事件一樣)。
22 :設置導航欄和狀態欄(只對4.4或以上有用)
這個就是用來設置app上方的界面,就是顯示WiFi標志 時間 電池信息什麼的
設置方法:
首先要打開activity的透明主題功能,可以把activity的主題設置繼承*.TranslucentDecor 主題,然後設置android:windowTranslucentNavigation或者android:windowTranslucentStatus的主題屬性為true,又或者在activity的代碼裡面開啟FLAG_TRANSLUCENT_NAVIGATION或是FLAG_TRANSLUCENT_STATUS的window窗口標識。
激活:
// 創建狀態欄的管理實例SystemBarTintManager tintManager = new SystemBarTintManager(this);
// 激活狀態欄設置tintManager.setStatusBarTintEnabled(true);
// 激活導航欄設置tintManager.setNavigationBarTintEnabled(true);
設置狀態欄顏色和圖片
// 設置一個顏色給系統欄
tintManager.setTintColor(Color.parseColor("#99000FF"));
// 設置一個樣式背景給導航欄
tintManager.setNavigationBarTintResource(R.drawable.my_tint);
// 設置一個狀態欄資源
tintManager.setStatusBarTintDrawable(MyDrawable);
23:Intent的Flag任用
在Activity中若用清除之前所有的Activity和Task 最好的方法是給Activity加個Flag FLAG_ACTIVITY_CLEAR_TASK 這個Flag的解釋是在此activity啟動之前,任何與此activity相關聯的task都會被清除。也就是說,此activity將變成一個空棧中新的最底端的activity,所有的舊activity都會被finish掉,這個標識僅僅和FLAG_ACTIVITY_NEW_TASK聯合起來才能使用。
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
若想保留2個Activity也就是說要在新Task裡保留2個Act 那麼最好的做法是一次啟動兩個Activity,具體操作如下:
Intent intent = new Intent(this,A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
intent = new Intent(this,B.class);
startActivity(intent);
這個時候系統會直接跳到B界面,同時A會放在Task的最底層,從B界面返回 會回到A界面。
24:獲取控件在屏幕中的位置
getLocationOnScreen
,計算該視圖在全局坐標系中的x,y值,(注意這個值是要從屏幕頂端算起,也就是索包括了通知欄的高度)//獲取在當前屏幕內的絕對坐標
getLocationInWindow,計算該視圖在它所在的widnow的坐標x,y值,//獲取在整個窗口內的絕對坐標 (不是很理解= =、)
getLeft,getTop,getBottom,getRight,這一組是獲取相對在它父親裡的坐標
如果在Activity的OnCreate()事件輸出那些參數,是全為0,要等UI控件都加載完了才能獲取到這些。
25:android:ellipsize的使用
EidtText和textview中內容過長的話自動換行,使用android:ellipsize與android:singleine可以解決,使只有一行。
EditText不支持marquee
用法如下:
在xml中
android:ellipsize = "end" 省略號在結尾
android:ellipsize = "start" 省略號在開頭
android:ellipsize = "middle" 省略號在中間
android:ellipsize = "marquee" 跑馬燈
android:singleline = "true"
當然也可以用代碼語句
tv.setEllipsize(TextUtils.TruncateAt.valueOf("END"));
tv.setEllipsize(TextUtils.TruncateAt.valueOf("START"));
tv.setEllipsize(TextUtils.TruncateAt.valueOf("MIDDLE"));
tv.setEllipsize(TextUtils.TruncateAt.valueOf("MARQUEE"));
tv.setSingleLine(true);
26:edittext光標
在XML中:Android:pidding = "10dp"就可以把光標往後移一點
在代碼中把光標設在字體後面:titleView.setSelection(titleView.getText().length()); ()裡為輸入框內容長度。
27:drawpidding與與drawableLeft
後者設置textview的左(可上 下 左 右)邊界圖片,前者用來設置text與drawable(圖片)的間隔。
28:中文加粗
TextView tv=(TextView)findViewById(R.id.TextView01);
TextPaint tp=tv.getPaint();
tp.setFakeBoldText(true);
其他自己加粗:
在xml文件中使用android:textStyle=”bold”
29:View中利用TAG傳值
例如 給一個動態View添加點擊事件,點擊事件中要獲得View中的某些值,那怎麼把值傳遞過去呢?這裡就要用到TAG了。
點擊事件可以這樣寫:
view.setOnClickListener(new ContactClick());
監聽事件可以這樣實現:
private class ContactClick implements OnClickListener {
@Override
public void onClick(View v) {
}
}
但是這樣的話得不到View裡的數據,點擊事件不能完成。
so,利用setTag與getTag來傳遞消息。
View中Tag有兩種用法:
1,View.setTag(Object tag);
API是這樣寫的: Sets the tag associated with this view. A tag can be used to mark a view in its hierarchy and does not have to be unique within the hierarchy. Tags can also be used to store data within a view without resorting to another data structure.
翻譯:設置與此視圖關聯的標簽。 tag可用於標記層次結構中的 view而層次結構不必是唯一的。標簽還可以用於存儲視圖中的數據,而不訴諸其他數據結構。(第二句話目測翻譯有問題)
與之配套使用 的是view.getTag(); API:the Object stored in this view as a tag。以一個tag返回存儲在View中的Object。
2,View.setTag(int key, Objecttag)
API: Sets a tag associated with this view and a key. A tag can be used to mark a view in its hierarchy and does not have to be unique within the hierarchy. Tags can also be used to store data within a view without resorting to another data structure. The specified key should be an id declared in the resources of the application to ensure it is unique (see the ID resource type). Keys identified as belonging to the Android framework or not associated with any package will cause an
IllegalArgumentException
to be thrown.
翻譯:設置與此視圖關聯的一個tag和一個key。tag可用於標記層次結構中查看層次結構中不必是唯一的。Tags還可以用於存儲視圖中的數據,而不訴諸其他數據結構。key應是指定的密鑰id中聲明的應用資源,以確保它是獨一無二的(見ID資源類型)。Keys 為屬於Android框架或不相關的任何包的密鑰,否則將導致拋出一個IllegalArgumentException。(翻譯有問題)
二者本質上沒有區別,都是傳值,但是①一般只是傳單個值,而②就克傳多個值。而在傳多個值時值得注意的是這個Key,他不能為普通的int型數據,它要的是與其他控件一樣的id,且不能是重復的,so解決方法是在value裡新建ids.xml文件 裡面存放id
eg:
在調用的時候用 R.id.tag_name 就可以解決問題了。
末了 完整版的解決方案是:
// 添加數據
view.setTag(R.id.tag_name, str1);
view.setTag(R.id.tag_address, str2);
// 添加監聽
view3.setOnClickListener(new ContactClick());
// 監聽事件
private class ContactClick implements OnClickListener {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//獲取數據
String name = (String) v.getTag(R.id.tag_name);
String address = (String) v.getTag(R.id.tag_address);
}
}
30:在代碼裡面無法設置textview文字居左問題
有時候在代碼裡面無法設置TextView的文字走向,那麼解決問題的方法是:
LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_VERTICAL);
tv.setLayoutParams(params);
tv.setGravity(Gravity.LEFT);
重新設置TextView的layout,然後再來設置文字走向。
31:監聽返回鍵
常常喲重寫返回鍵事件,一般是去重寫按鈕點擊事件,然後再判斷是否是返回鍵 是否是按下什麼的,這樣做一般比較繁瑣,android裡有onBackPress()方法,重寫它就是了
32:遍歷Map
在不知道Map數據情況下,需要遍歷Map裡面的數據,那麼需要對map進行遍歷,有方法如下:
Iterator it = levelMap.entrySet().iterator();
while (it.hasNext()) {
//獲得節點
Entry entry = (Entry) it.next();
//獲得節點的key values
String key = (String) entry.getKey();
String value = (String) entry.getValue();
}
****方法不唯一
over~
33:遍歷list並刪除某個item注意事項
遍歷list的方法很多,但如果在遍歷的時候需要刪除某個節點的話,那麼不能用for()循環來刪除了,使用for循環刪除的問題是這樣出現的,我刪除了i= 5的節點(i++之後i= 6了),那麼我做下一次判斷的時候就直接去判讀新list的i = 6處的值了,但是新list的長度-1了,並且原來i>5之後的內容都往前移了一位,原來i= 6的節點跑到了i= 5處,但是從上文可知,i= 5節點沒有判斷,so error occurs。
解決方法:1,構建一個與待遍歷的list一樣的list,一個作為遍歷的對象,一個作為刪除的對象,二者分開就沒有問題了,最後把刪除對象的值賦值待遍歷對象就OK了。
2,使用Iterator來遍歷,需要刪除的時候使用it.remove()就行了。(it.remove()只能調用一次,多次就拋異常了)
3,還是使用for來遍歷。無論用Iterator還是for(),刪除的都是當前item,由上文可知,因為刪除了i=5節點之後,下一次就判斷i=6的節點,原來的i= 6節點(新list的i= 5)沒有判斷,那麼每刪除一次節點之後把i的值減一不就行了嗎?! 下一次判斷的時候還是從i= 5開始,而i= 5剛好是之前的i= 6,這樣就避免了之前的漏判問題,那就OK了(此法只是構想,還沒實踐,不過應該可以)。
over~
34:webView禁止復制粘貼
長按選擇粘貼文字是webView的onLongClickListener功能,若要禁止復制,那麼攔截這個事件即可。
this.appView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
return true;//禁止事件返回
}
});
35:防截屏
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
36:背景變暗
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 0.3f;(比1小即可)
getWindow().setAttributes(lp);
37 :截屏並保存
activity.getWindow().getDecorView().setDrawingCacheEnabled(true);
Bitmap bmp = activity.getWindow().getDecorView().getDrawingCache();
try {
OutputStream out = new FileOutputStream(Filename);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
38 :截屏模擬點擊
android裡有時候把數據和點擊事件封裝好了以後,需要人為去觸發(如pager的默認首頁),但是在程序裡又沒法點擊,這個時候就可以用view.performClick()。
前提:有view.onClickListener方法設置了監聽。
注意:如果同時使用了view.setOnTouchListener()方法,則有可能存在攔截view.performClick()的響應事件,因為當view.OnTouchEvent()在event.getAction() == MotionEvent.ACTION_DOWN時返回false,系統會認為view不需要處理Touch事件,則後續的Touch事件(move、up、click)就不會被傳進來,所以也不會觸發view.performClick(),而view.setOnTouchListener()相當於是重寫了view.OnTouchEvent(),所以在寫view的TouchListener處理時,需要留意view是否存在點擊事件監聽,如果有,則在適當的位置使用view.performClick()觸發點擊事件。
39:時鐘
時鐘控件包括AnalogClock和DigitalClock,它們都負責顯示時鐘,所不同的是AnalogClock控件顯示模擬時鐘,且只顯示時針和分針,而DigitalClock顯示數字時鐘,可精確到秒。
二者都是直接在xml裡加控件,不需要在java代碼控制,直接就可以自動顯示時間。
40:ExpandableListView默認全部展開且點擊不收縮
全部展開:
//展開所有的Group
private void expandELV(ExpandableListView elv,
BaseExpandableListAdapter adapter) {
for (int i = 0; i < adapter.getGroupCount(); i++) {
elv.expandGroup(i);
}
}
//屏蔽group的點擊事件
private void blockGroupClick(ExpandableListView elv) {
elv.setOnGroupClickListener(new OnGroupClickListener() {
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
return true;
}
});
}
41:點擊密碼可見隱藏
android中為EditText提供了setTransformationMethod來控制密碼的顯隱。主要代碼如下:
/* show the password*/
edittext.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
/* hide the password */
edittext.setTransformationMethod(PasswordTransformationMethod.getInstance());
或者利用InputType也行。
//顯示為普通文本
pwdEdit.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
//顯示為密碼
pwdEdit.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_PASSWORD);
42:導入自定義屬性
xmlns:hyman="http://schemas.android.com/apk/res-auto"