編輯:關於Android編程
在安卓開發中,谷歌已經為我們提供了許多原生控件,基本上能夠滿足我們日常的開發需求,但是某些項目中原生控件可能達不到產品所要求的各式各樣的酷炫效果或功能效果,這個時候我們只能自己自定義控件來滿足項目需求,我們知道自定義控件包括三種方式:
1繼承控件,即繼承谷歌提供的原生控件,在此基礎上提供一些原生控件不具備的功能,如github上各種酷炫效果的開源組件基本上都是采用的這種方式.
2組合控件:即組合多個原生控件來達到某些單個原生控件原本不具備的功能,這個在日常開發中應該是使用的比較多的,如基本上每個App都存在一個標題欄,而這些標題欄是可以被復用的,此時我們可以將其抽象出來組合為一個控件,這樣在需要標題欄的地方直接使用該控件。(當然也可以采用include布局的方式,但是這樣僅僅只是界面復用而已,功能不能復用)
3自繪控件:即直接繼承自View類,然後自己重寫onDraw方法,某些情況下可能需要重寫onMeasure方法。
這三種方式,第一種方式我們使用的很少,因為github上大量優秀的開源組件就是采用的這種方式,如下拉刷新上拉加載的listView,側滑刪除的listView等,因此我們只需要直接拿來用就可以了,不要去重復造輪子,當然如果是學習自定義控件的知識的話,我們也可以直接去閱讀這些開源項目的源代碼,第二種方式我們使用的比較多的地方就是一個App的標題欄,通常都是采用的這種方式來完成的,第三種方式在一般的項目中很少使用到,除非項目需要完成一些復雜的效果。本博客將以第二中方式即組合控件為例來講解安卓自定義控件的使用,將以模仿騰訊QQ的標題欄為例來教大家如何自定義組合控件。首先我們來看一下騰訊QQ的標題欄。然後按照這個樣子我們自己模仿自定義一個標題欄控件。當然QQ的標題欄還是比較復雜的,因為標題欄中的文字會隨著用戶點擊底部不同的button而顯示不同的內容,當然這個功能個也很好實現,關鍵是如果要截圖的話得截幾張圖,這裡我就選擇最具代表性的一個界面,其余的看官可以自己用QQ試一下。
可以看到在左側是一個ImageView,中間是兩個button,點擊不同button顯示不同內容,當然這是在消息界面,因此中間是兩個button,而在聯系人與動態界面中間只顯示文字而已,因此此時中間是TextView,右側基本上也是同樣的道理。所以第一步我們需要在layout布局文件中組合控件來到達這樣的一個界面效果。
common_title_bar的layout文件如下:
可以看到該布局的根布局是一個RelativeLayout,當然這個是和具體的組合控件的界面相關的,不過像這種標題欄我們一般都使用RelativeLayout布局,然後在該布局中我們基本上按照前面的分析組合了幾個原生的控件,當然那個ImageView為了達到和騰訊QQ一樣的效果,我采用的是開源的CircleImageView,這些組合控件之間的位置關系通過相對布局來控制。
接下來就是自定義組合控件了,代碼如下:
public class TitleBarView extends RelativeLayout { private Context mContext; Button rightBtn; TextView center_tv; LinearLayout title_linearlayout; Button linear_leftBtn; Button linear_rightBtn; ImageView leftImg; public TitleBarView(Context context) { super(context); mContext=context; findView(); // TODO Auto-generated constructor stub } public TitleBarView(Context context, AttributeSet attrs) { super(context, attrs); mContext=context; findView(); } public void findView() { LayoutInflater.from(mContext).inflate(R.layout.common_title_bar, this); leftImg=(ImageView) findViewById(R.id.title_bar_leftImg); rightBtn=(Button)findViewById(R.id.title_bar_rightBtn); center_tv=(TextView) findViewById(R.id.center_tv); title_linearlayout=(LinearLayout) findViewById(R.id.title_bar_linearLayout); linear_leftBtn=(Button) findViewById(R.id.title_bar_linear_leftBtn); linear_rightBtn=(Button) findViewById(R.id.title_bar_linear_rightBtn); } public void setCommonTitle(int leftImg_vi,int centerLinear_vi,int textView_vi,int rightBtn_vi) { leftImg.setVisibility(leftImg_vi); title_linearlayout.setVisibility(centerLinear_vi); center_tv.setVisibility(textView_vi); rightBtn.setVisibility(rightBtn_vi); } public void setDefaultImgLeft(int icon){ Drawable img=mContext.getResources().getDrawable(icon); leftImg.setImageDrawable(img);; } public void setUserImgLeft(Bitmap bitmap) { leftImg.setImageBitmap(bitmap); } public void setBtnRight(int icon) { rightBtn.setText(icon); } public void setBtnRightText(String str) { rightBtn.setText(str); } public void setBtnRightIcon(int icon) { Drawable img=mContext.getResources().getDrawable(icon); rightBtn.setBackgroundDrawable(img); } public void setBtnRightDrawable(Drawable img) { rightBtn.setBackgroundDrawable(img); } public void setTitleLeft(int resId){ linear_leftBtn.setText(resId); } public void setTitleRight(int resId){ linear_rightBtn.setText(resId); } public void setTitleText(int txtRes){ center_tv.setText(txtRes); } public void setLefImgtOnclickListener(OnClickListener listener){ leftImg.setOnClickListener(listener); } public void setBtnRightOnclickListener(OnClickListener listener){ rightBtn.setOnClickListener(listener); } public ImageView getTitleLeft(){ return leftImg; } public Button getTitleRight(){ return rightBtn; } }可以看到,自定義的TitleBarView繼承自RelativeLayout,因為我們前面布局文件中根布局使用的是RelativeLayout,當然也可以不這麼做,但這樣做規范一些,然後自定義控件TitleBarView的構造函數中使用LayoutInflater.from(mContext).inflate(R.layout.common_title_bar, this);語句將common_title_bar布局文件中的布局解析出來,當然我這裡為了代碼規范,在自定義控件TitleBarView的構造函數中使用的是findView()函數,然後在該函數中對控件進行初始化,這樣做代碼邏輯清晰。然後在該TitleBarView中提供一些
方法來控制組合控件的可見性與某些功能,因為我們知道騰訊QQ的標題欄隨著底部不同button被點擊標題欄中間會顯示不同的控件,這我們在前面已經分析過,因此我們需要提供一個控制這些組合控件可見性的方法,除了可見性外還需提供一些功能方法,這個視具體業務需求而定,這樣會具備更好的擴展性。
通過前面兩個步驟,一個自定義的組合控件就已經完成了,余下的就是如何使用了,這個也很簡單,在需要使用該自定義控件的布局文件中使用該自定義控件完整的路徑名即可,即包名+類名,如下所示:
運行之後效果如下:
這樣一個高仿騰訊QQ的標題欄就做出來了,當然這個運行結果是我的高仿騰訊QQ即時IM項目的運行結果,前面的代碼也是在該項目中用到的代碼,該項目已開源,如果看官想體驗完整的效果可以follow我的github,start與fork我的開源項目,我的github:https://github.com/HuTianQi上一篇,初步開發了這個應用,功能都有了(見http://www.jb51.net/article/96992.htm 點擊打開鏈接)。但是遺留了兩個問題:1、還是無法卸載
前言:在上篇中,分析了MediaPlayer的從創建到setDataSource過程,盡管看了代碼,但是沒有從MediaPlayer生態上認識各類庫之間依賴調用關系,在本
Android手機話筒采樣有部分代碼是在網上找的,具體不記得了。 使用采樣結果以及是自己的app的功能代碼: 1. 在一部分app中會需要對話筒的音頻輸入獲取使用,比如之
今天給大家帶來的是僅僅使用一個TextView實現一個高仿京東、淘寶、唯品會等各種電商APP的活動倒計時。最近公司一直加班也沒來得及時間去整理,今天難得休息想把這個分享給