編輯:關於android開發


Android系統中,繼承Android系統自帶的View或者ViewGroup控件或者系統自帶的控件,並在這基礎上增加或者重新組合成我們想要的效果。
系統控件無法滿足需求時,需要自定義控件。
1.使用系統控件,重新組合,實現自定義的效果,案例有:
優酷環形菜單、廣告條循環滾動(Viewpager)、下拉菜單(spinner)、下拉框(PopupWindow、ListView)
2.自己定義一個類繼承View ,實現特定的效果,案例有:
自定義開關按鈕、水波紋效果
3.自己定義一個類繼承ViewGroup,實現特定的效果,案例有:
仿ViewPager的效果實現 、 仿網易側滑菜單
4.自定義屬性:給自己的控件,添加自己的屬性,通過demo了解系統解析屬性的過程,
並給上一個例子開關按鈕,添加新屬性。
Android本身提供了很多控件,如:
文本控件 TextView和EditText;
圖片控件 ImageView
按鈕控件 Button和ImageButton
進度條 ProgressBar
單選按鈕 RadioButton和RadioGroup
復選按鈕 CheckBox
狀態開關按鈕ToggleButton
時鐘控件 AnalogClock和DigitalClock
日期與時間選擇控件DatePicker和TimePicker等。
. . .
使用原則:盡量使用系統的控件,在系統控件沒法達到我們的需求的時候才需要自定義控件。再定義控件會帶來工作量,例如修改bug.
文本控件TextView 和EditText
TextView 控件繼承自 View 類。TextView控件的功能是向用戶顯示文本內容,TextView不允許編輯。
EditText控件繼承自 TextView。EditText與TextView 最大的不同是 EditText是可以編輯的
圖片控件ImageView
ImageView 控件負責顯示圖片,其圖片來源既可以是資源文件的id,也可以是Drawable對象或 Bitmap 對象,還可以是 內容提供者(Content Provider)的Uri.

按鈕控件Button 和 ImageButton
Button控件繼承自 TextView 類,Button 的用法比較簡單,主要是為 Button 設置一個點擊事件監聽器,並在編寫按鈕點擊事件的處理代碼。
ImageButton 控件 繼承自 ImageView。
ImageButton與Button相同之處:都用於響應按鈕的點擊事件
不同之處:ImageButton只能顯示圖片;Button用於顯示文字

進度條ProgressBar
ProgressBar繼承自 View,用於顯示正在運行的狀態。有兩種顯示形式:一種是環形顯示只用於顯示狀態,沒有具體的進度。第二種是水平顯示,可以顯示具體 的進度。
通過設置不同的Style顯示不同的樣式:
環形樣式
水平樣式

單選按鈕 RadioButton 和復選按鈕 CheckBox
CheckBox 和RadioButton 都繼承自CompoundButton,都只有選中和未選中兩種狀態,可以通過checked屬性來設置。
不同的是RadioButton 是單選按鈕,在一個RadioGroup中只能有一個RadioButton按鈕處於選中狀態;CheckBox 則可以有多個按鈕被選中。

狀態開關按鈕ToggleButton
ToggleButton 控件是繼承自 CompoundButton。ToggleButton 的狀態只能是選中和未選中,並且需要為不同的狀態設置不同的顯示文本。除了繼承自父類的一 些屬性和方法之外,ToggleButton 也具有一些自己的屬性。

時鐘控件AnalogClock 和 DigitalClock
AnalogClock繼承自 View,用於顯示模擬時鐘只顯示時針和分針。
DigeitalClock 繼承自 TextView。用於顯示數字時鐘可精確到秒。 時鐘控件比較簡單,只需要在布局文件中聲明控件即可。

日期選擇器 DatePicker 和時間選擇器 TimePicker
DatePicker 繼承自FrameLayout類,日期選擇控件的主要功能是向用戶提供包含年、月、日的日期數據,並允許用戶對其修改。如果要捕獲這個修改,可以 為 DatePicker添加 onDateChangedListener 監聽器。
TimePicker 同樣繼承自FrameLayout 類。時間選擇控件向用戶顯示一天中的時間,可以為24小時制,可以為AM/PM 制,並允許用戶進行修改。如果要捕獲用 戶的修改事件,需要為TimePicker 添加OnTimeChangedListener 監聽器

知識鏈接:
android WheelView組件(滑輪組件)的使用 : http://www.myexception.cn/android/1236819.html
系統提供的控件雖然很豐富,但是,還遠遠不夠。有的時候我們必須要自己定義控件來滿足我們的要求。下面的案例,詳細分析自定義控件的使用:

運行演示做好的優酷菜單效果,並且講解實現思路;因為現在優酷已經更換界面,引用此界面主要為講解自定義控件實現的思想。
1_創建工程YukuMenuDemo,圖片全部拷貝到drawable-hdpi目錄下
2_實現三個圓環-最裡面的圓環
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/level1"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:background="@drawable/level1"
android:layout_width="100dip"
android:layout_height="50dip" >
</RelativeLayout>
</RelativeLayout>
3_實現三個圓環-中間園環
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/level2"
android:layout_width="180dip"
android:layout_height="90dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" >
</RelativeLayout>
<RelativeLayout
android:id="@+id/level1"
android:layout_width="100dip"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1" >
</RelativeLayout>
</RelativeLayout>
4_實現三個圓環-最外環
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/level3"
android:layout_width="280dip"
android:layout_height="140dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3" >
</RelativeLayout>
<RelativeLayout
android:id="@+id/level2"
android:layout_width="180dip"
android:layout_height="90dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" >
</RelativeLayout>
<RelativeLayout
android:id="@+id/level1"
android:layout_width="100dip"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1" >
</RelativeLayout>
</RelativeLayout>
5_最裡環的的圖標
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/level3"
android:layout_width="280dip"
android:layout_height="140dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3" >
</RelativeLayout>
<RelativeLayout
android:id="@+id/level2"
android:layout_width="180dip"
android:layout_height="90dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" >
</RelativeLayout>
<RelativeLayout
android:id="@+id/level1"
android:layout_width="100dip"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/icon_home" />
</RelativeLayout>
</RelativeLayout>
6_中間環的圖標
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/level3"
android:layout_width="280dip"
android:layout_height="140dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3" >
</RelativeLayout>
<RelativeLayout
android:id="@+id/level2"
android:layout_width="180dip"
android:layout_height="90dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="10dip"
android:src="@drawable/icon_search" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dip"
android:src="@drawable/icon_menu" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="10dip"
android:src="@drawable/icon_myyouku" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/level1"
android:layout_width="100dip"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/icon_home" />
</RelativeLayout>
</RelativeLayout>
7_最外環的圖標的左邊部分
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/level3"
android:layout_width="280dip"
android:layout_height="140dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3" >
<ImageView
android:id="@+id/channel1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dip"
android:layout_marginLeft="10dip"
android:src="@drawable/channel1" />
<ImageView
android:id="@+id/channel2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/channel1"
android:layout_alignLeft="@id/channel1"
android:layout_marginLeft="20dip"
android:layout_marginBottom="10dip"
android:src="@drawable/channel2" />
<ImageView
android:id="@+id/channel3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/channel2"
android:layout_alignLeft="@id/channel2"
android:layout_marginBottom="8dp"
android:layout_marginLeft="35dp"
android:src="@drawable/channel3" />
<ImageView
android:layout_marginTop="10dip"
android:id="@+id/channel4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/channel4" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/level2"
android:layout_width="180dip"
android:layout_height="90dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" >
...............
</RelativeLayout>
<RelativeLayout
android:id="@+id/level1"
android:layout_width="100dip"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1" >
...............
</RelativeLayout>
</RelativeLayout>
8_最外環的圖標的右邊部分
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/level3"
android:layout_width="280dip"
android:layout_height="140dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3" >
<ImageView
android:id="@+id/channel1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dip"
android:layout_marginLeft="10dip"
android:src="@drawable/channel1" />
<ImageView
android:id="@+id/channel2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/channel1"
android:layout_alignLeft="@id/channel1"
android:layout_marginBottom="10dip"
android:layout_marginLeft="20dip"
android:src="@drawable/channel2" />
<ImageView
android:id="@+id/channel3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/channel2"
android:layout_alignLeft="@id/channel2"
android:layout_marginBottom="8dp"
android:layout_marginLeft="35dp"
android:src="@drawable/channel3" />
<ImageView
android:id="@+id/channel4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dip"
android:src="@drawable/channel4" />
<ImageView
android:id="@+id/channel7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="10dip"
android:layout_marginRight="10dip"
android:src="@drawable/channel7" />
<ImageView
android:id="@+id/channel6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/channel7"
android:layout_alignRight="@id/channel7"
android:layout_marginBottom="10dip"
android:layout_marginRight="20dip"
android:src="@drawable/channel6" />
<ImageView
android:id="@+id/channel5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/channel6"
android:layout_alignRight="@id/channel6"
android:layout_marginBottom="10dip"
android:layout_marginRight="35dip"
android:src="@drawable/channel7" />
</RelativeLayout>
................
................
</RelativeLayout>
public class MainActivity extends Activity implements OnClickListener {
private RelativeLayout level1;
private RelativeLayout level2;
private RelativeLayout level3;
private ImageView icon_home;
private ImageView icon_menu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
level1 = (RelativeLayout) findViewById(R.id.level1);
level2 = (RelativeLayout) findViewById(R.id.level2);
level3 = (RelativeLayout) findViewById(R.id.level3);
icon_home = (ImageView) findViewById(R.id.icon_home);
icon_menu = (ImageView) findViewById(R.id.icon_menu);
icon_home.setOnClickListener(this);
icon_menu.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.icon_home://相應home的點擊事件
break;
case R.id.icon_menu://相應menu的點擊事件
break;
}
}
private boolean isLevel3Show = true;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.icon_home:// 相應home的點擊事件
break;
case R.id.icon_menu:// 相應menu的點擊事件
if (isLevel3Show) {
Tools.hideView(level3);
isLevel3Show = false;
} else {
Tools.showView(level3);
isLevel3Show = true;
}
break;
}
}

/**
* @author m
*
*/
public class Tools {
public static void hideView(View view) {
/**
* fromDegrees 從多少度開始
* toDegrees 旋轉到度
* pivotX 中心點x坐標
* pivotY 中心點y坐標
*/
RotateAnimation ra = new RotateAnimation(0, 180, view.getWidth()/2, view.getHeight());
//播放時常
ra.setDuration(500);
//停留在播放完成狀態
ra.setFillAfter(true);
view.startAnimation(ra);
}
public static void showView(View view) {
RotateAnimation ra = new RotateAnimation(180, 360, view.getWidth() / 2,
view.getHeight());
ra.setDuration(500);
ra.setFillAfter(true);
view.startAnimation(ra);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.icon_home:// 相應home的點擊事件
if (isLevel2Show) {
//如果二級菜單式顯示的,隱藏二級菜單
Tools.hideView(level2);
//判斷三級菜單的狀態,如果是顯示,同時也隱藏三級菜單
if(isLevel3Show){
Tools.hideView(level3);
}
isLevel2Show = false;
} else {
//如果二級才能使隱藏的,那麼顯示二級菜單
Tools.showView(level2);
isLevel2Show = true;
}
break;
case R.id.icon_menu:// 相應menu的點擊事件
..................
break;
}
}
/**
* @author m
*
*/
public class Tools {
public static void hideView(View view) {
hideView(view, 0);
}
public static void showView(View view) {
showView(view, 0);
}
/**
* 延遲顯示
*
* @param view
* @param i
*/
public static void showView(View view, int i) {
RotateAnimation ra = new RotateAnimation(180, 360, view.getWidth() / 2,
view.getHeight());
ra.setDuration(500);
ra.setFillAfter(true);
ra.setStartOffset(i);
view.startAnimation(ra);
}
/**
* 延遲隱藏
*
* @param view
* @param i
* 延遲隱藏的時間
*/
public static void hideView(View view, int i) {
/**
* fromDegrees 從多少度開 toDegrees 旋轉到度 pivotX x坐標 pivotY y坐標
*/
RotateAnimation ra = new RotateAnimation(0, 180, view.getWidth() / 2,
view.getHeight());
// 播放時常
ra.setDuration(500);
// 停留在播放完成狀態
ra.setFillAfter(true);
ra.setStartOffset(i);
view.startAnimation(ra);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
if (isLevel1Show) {
// 如果一級菜單式顯示的,那麼隱藏 一級菜單
Tools.hideView(level1);
isLevel1Show = false;
// 同時判斷 隱藏二級、三級菜單
if (isLevel2Show) {
Tools.hideView(level2, 200);
isLevel2Show = false;
if (isLevel3Show) {
Tools.hideView(level3, 300);
isLevel3Show = false;
}
}
} else {
// 如果一級菜單式隱藏的,那麼就要顯示一級菜單
Tools.showView(level1);
isLevel1Show = true;
// 同時要顯示二級菜單
Tools.showView(level2,200);
isLevel2Show = true;
}
return true;
}
return super.onKeyDown(keyCode, event);
}
/**
* @author m
*
*/
public class Tools {
public static void hideView(ViewGroup view) {
hideView(view, 0);
}
public static void showView(ViewGroup view) {
showView(view, 0);
}
/**
* 延遲顯示
*
* @param view
* @param i
*/
public static void showView(ViewGroup view, int startOffset) {
RotateAnimation ra = new RotateAnimation(180, 360, view.getWidth() / 2,
view.getHeight());
ra.setDuration(500);
ra.setFillAfter(true);
ra.setStartOffset(startOffset);
view.startAnimation(ra);
// view.setVisibility(View.VISIBLE);
// view.setEnabled(true);
for (int i = 0; i < view.getChildCount(); i++) {
view.getChildAt(i).setEnabled(true);
}
}
/**
* 延遲隱藏
*
* @param view
* @param i
* 延遲隱藏的時間
*/
public static void hideView(ViewGroup view, int startOffset) {
/**
* fromDegrees 從多少度開 toDegrees 旋轉到度 pivotX x坐標 pivotY y坐標
*/
RotateAnimation ra = new RotateAnimation(0, 180, view.getWidth() / 2,
view.getHeight());
// 播放時常
ra.setDuration(500);
// 停留在播放完成狀態
ra.setFillAfter(true);
ra.setStartOffset(startOffset);
view.startAnimation(ra);
// view.setVisibility(View.GONE);
// view.setEnabled(false);
for (int i = 0; i < view.getChildCount(); i++) {
view.getChildAt(i).setEnabled(false);
}
}
}

1_創建工程名:
首頁影片推廣效果,包名為:com.bokeyuan.viewpager,並且拷貝圖片到drawable-hdpi目錄
2_寫布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="200dip" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/viewpager"
android:background="#33000000"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="5dip" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="三個火槍手"
android:textColor="#ffffff"
android:textSize="18sp" />
<LinearLayout
android:id="@+id/ll_point_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:orientation="horizontal" >
</LinearLayout>
</LinearLayout>
</RelativeLayout>
3.實例化ViewPager和關聯其源代碼:
代碼實例化:
public class MainActivity extends Activity {
private ViewPager viewpager;
private LinearLayout ll_point_group;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewpager = (ViewPager) findViewById(R.id.viewpager);
ll_point_group = (LinearLayout) findViewById(R.id.ll_point_group);
}
}
關聯源代碼:
1.刪除工程裡面的Android Depandencies,刪除後會報錯,不要理會。看下面

2.添加libs目錄下的Android-support-v4.jar包
選中-->右鍵-->build path-->add to build path
3.關聯源代碼
目錄:C:\android\adt-bundle-windows-x86_64-20130219\sdk\extras\android\support\v4\src\java
點擊ViewPager類,出現圖標;

大家對於v4包都已經很熟悉了,現在在新建android項目時,v4包是默認導入的。v7包出來沒多長時間,用的人也不多,主要對3.0以下版本提 供 ActionBar支持,以及SearchView,PopupMenu等控件的支持。因為一些開源框架已經實現對3.0以下版本ActionBar的支 持,所以v7包的使 用意義也不是很大。
知識拓展:
如果jar包導入錯誤,怎麼修改呢?
右鍵工程---->properties---->Java Build Path --->Libraries-->選擇android-support-v4.jar展開---->Editor--->External Folder
4.ViewPager的原理

能顯示很多頁面,者些頁面可以是圖片也可以是布局文件。
4_設置圖片資源ID和圖片標題集合和准備ImageView列表數據
// 圖片資源ID
private final int[] imageIds = {
R.drawable.a,
R.drawable.b,
R.drawable.c,
R.drawable.d,
R.drawable.e };
// 圖片標題集合
private final String[] imageDescriptions = {
"鞏俐不低俗,我就不能低俗",
"撲樹又回來啦!再唱經典老歌引萬人大合唱",
"揭秘北京電影如何升級",
"樂視網TV版大派送",
"熱血屌絲的反殺" };
//准備數據
imageList = new ArrayList<ImageView>();
for(int i=0;i<imageIds.length;i++){
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(imageIds[i]); imageList.add(imageView);
}
5_為ViewPager設置適配器
private class MyPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
// 頁面或者圖片的總數
return imageList.size();
}
/**
* 功能:給ViewPager添加指定的view
* container 就是ViewPager,其實就是容器。
* position 具體頁面或者圖片的位置
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
System.out.println("instantiateItem=="+position);
View view = imageList.get(position);
container.addView(view);
//返回的值,不一定是View ,也可以是和View有關系的任意的Object
// return super.instantiateItem(container, position);
return view;
}
/**
* 判斷某個page和object的關系
* object 是 instantiateItem的返回值
*/
@Override
public boolean isViewFromObject(View view, Object object) {
// if(view ==object){
// return true;
// }else{
// return false;
// }
return view ==object;
}
/**
* 銷毀指定位置上的View或者object
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
System.out.println("destroyItem=="+position);
container.removeView((View) object);
// super.destroyItem(container, position, object);
}
}
6_解決運行報錯
選中項目--->右鍵--->Java Build Path --->
order export--->勾選android-support-v4.jar--->千萬不要忘了clean

1_根據不同圖片顯示不同描述信息
viewpager.setOnPageChangeListener(new OnPageChangeListener() {
/**
* 當頁面被選擇了回調
* position 當前被顯示的頁面的位置:從0開始
*/
@Override
public void onPageSelected(int position) {
tv_image_desc.setText(imageDescriptions[position]);
}
/**
* 當頁面滑動了調用該方法
*/
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
/**
* 當頁面狀態發送變化的調用防方法
* 靜止--滑動
* 滑動-靜止
*
*/
@Override
public void onPageScrollStateChanged(int state) {
}
});
2.用shape資源定義點和背景
創建drawable目錄裡面創建文件
point_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<size android:height="5dip" android:width="5dip" />
<solid android:color="#55000000"/>
</shape>
point_focused.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<size android:height="5dip" android:width="5dip" />
<solid android:color="#aaffffff"/>
</shape>
point_selsetor.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:drawable="@drawable/point_focused" />
<item android:state_enabled="false" android:drawable="@drawable/point_normal" />
</selector>
3.代碼裡面添加指示點
for(int i=0;i<imageIds.length;i++){
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(imageIds[i]);
imageViews.add(imageView);
//添加指示點
ImageView point = new ImageView(this);
point.setBackgroundResource(R.drawable.point_selsetor);
ll_point_group.addView(point);
//默認情況下,第一個小點enable為true
if(i ==0){
point.setEnabled(true);
}else{
point.setEnabled(false);
}
}
4_設置改變指示點的狀態
如字體加粗部分
/**
* 上次的位置
*/
private int lastPointIndex;
viewpager.setOnPageChangeListener(new OnPageChangeListener() {
/**
* 當頁面被選擇了回調
* position 當前被顯示的頁面的位置:從0開始
*/
@Override
public void onPageSelected(int position) {
System.out.println("onPageSelected="+position);
tv_image_desc.setText(imageDescriptions[position]);
//設置指示點的狀態 enable 的狀態為true或者為false;
ll_point_group.getChildAt(position).setEnabled(true);
ll_point_group.getChildAt(lastPointIndex).setEnabled(false);
lastPointIndex = position;
}
/**
* 當頁面滑動了調用該方法
*/
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
/**
* 但頁面狀態發送變化的調用防方法
* 靜止--滑動
* 滑動-靜止
*
*/
@Override
public void onPageScrollStateChanged(int state) {
System.out.println("onPageScrollStateChanged===state=="+state);
}
});
5.設置指示點的間距
如字體加粗部分
for(int i=0;i<imageIds.length;i++){
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(imageIds[i]);
imageViews.add(imageView);
//添加指示點
ImageView point = new ImageView(this);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, -2);
params.leftMargin = 15;
point.setLayoutParams(params);
point.setBackgroundResource(R.drawable.point_selsetor);
ll_point_group.addView(point);
//默認情況下,第一個小點enable為true
if(i ==0){
point.setEnabled(true);
}else{
point.setEnabled(false);
}
}
注意導入包的時候,當前控件放入什麼布局就導入誰的LayoutParams的。
6_設置可以循環滑動
viewpager.setOnPageChangeListener(new OnPageChangeListener() {
/**
* 當頁面被選擇了回調
* position 當前被顯示的頁面的位置:從0開始
*/
@Override
public void onPageSelected(int position) {
int myIndex = position % imageViews.size();
System.out.println("onPageSelected="+position);
tv_image_desc.setText(imageDescriptions[myIndex]);
//設置指示點的狀態 enable 的狀態為true或者為false;
ll_point_group.getChildAt(myIndex).setEnabled(true);
ll_point_group.getChildAt(lastPointIndex).setEnabled(false);
lastPointIndex = myIndex;
}
..............................
});
}
private class MyPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
//得到數據的總數
// return imageViews.size();
return Integer.MAX_VALUE;
}
/**
* 給ViewPager添加指定的View
* container 是ViewPage,他是一個容器
* position 要實例化的view的位置
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
// System.out.println("instantiateItem=="+position);
//實例化View
View view = imageViews.get(position%imageViews.size());
container.addView(view);
//返回值,不一定要是View對象,也可以是和View有關系的任意object
// return super.instantiateItem(container, position);
return view;
}
......................
}
7_解決左滑沒有效果問題
//要求剛好是imageViews.size()的整數倍 int item = Integer.MAX_VALUE/2-Integer.MAX_VALUE/2%imageViews.size(); //讓ViewPager跳轉到指定的位置,應該保證是imageView.size()的整數倍 viewpager.setCurrentItem(item ); //11 和 101
實現方式有多種方案:
1.定時器 timer + Handler
2.while true 循環 sleep + Handler;
3.ClockManger + Handler ;
4.Handler
我們采用常用的方式Handler
/**
* 是否自定滑動運行中
*/
private boolean isRunning = false;
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
viewpager.setCurrentItem(viewpager.getCurrentItem()+1);
if(isRunning){
handler.sendEmptyMessageDelayed(0, 4000);
}
};
};
在onCreate中寫上
isRunning = true;
handler.sendEmptyMessageDelayed(0, 2000);
下拉框效果:
在editText的右邊放置一個小箭頭的圖片,點擊圖片,在editText的下方彈出一個popupWindow,並對popupWindow進行一些設置即得到想要的效果。

下拉框,把需要的圖片拷貝到工程中,包名:com.bokeyuan.popupwindow
代碼如下
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<EditText
android:id="@+id/et_input"
android:paddingRight="40dip"
android:layout_marginTop="20dip"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<ImageView
android:id="@+id/dowan_arrow"
android:layout_alignRight="@id/et_input"
android:layout_alignTop="@id/et_input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:layout_marginRight="5dip"
android:background="@drawable/down_arrow"/>
</RelativeLayout>
public class MainActivity extends Activity {
private EditText et_input;
private ImageView downArrow;
/**
* 裝數據的集合
*/
private ArrayList<String> msgList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_input = (EditText) findViewById(R.id.et_input);
downArrow = (ImageView) findViewById(R.id.dowan_arrow);
//准備數據
msgList = new ArrayList<String>();
for(int i=0;i<30;i++){
msgList.add("aaaaaaaaaa"+i);
}
}
}
downArrow.setOnClickListener(this);
//浮懸的窗體
private PopupWindow popupWindow;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.dowan_arrow:
if(popupWindow == null){
popupWindow = new PopupWindow(this);
//設置高和寬
popupWindow.setWidth(et_input.getWidth());
popupWindow.setHeight(200);
//設置窗體的內容
//TODO ListView 還沒有初始化
popupWindow.setContentView(listView);
}
popupWindow.showAsDropDown(et_input, 0, 0);
break;
default:
break;
}
在onCreate方法中實例化ListView
//實例化ListView listView = new ListView(this); listView.setAdapter(new MyAdapter());
自定義適配器
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return msgList.size();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
if(convertView != null){
view = convertView;
holder = (ViewHolder) view.getTag();
}else{
view = View.inflate(MainActivity.this, R.layout.list_popupwindow_item, null);
holder = new ViewHolder();
holder.iv_user = (ImageView) view.findViewById(R.id.iv_user);
holder.tv_tilte = (TextView) view.findViewById(R.id.tv_tilte);
holder.iv_delete = (ImageView) view.findViewById(R.id.iv_delete);
view.setTag(holder);
}
holder.tv_tilte.setText(msgList.get(position));
holder.iv_delete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//1.把點擊的條在列表中移除
msgList.remove(position);
//2.更新數據
notifyDataSetChanged();
}
});
return view;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
}
class ViewHolder{
ImageView iv_user;
TextView tv_tilte;
ImageView iv_delete;
}
每條布局文件代碼list_popupwindow_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="55dip"
android:gravity="center_vertical"
android:padding="15dip" >
<ImageView
android:id="@+id/iv_user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/user"
android:padding="5dp" />
<TextView
android:id="@+id/tv_tilte"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="aaaaaaaaa1" />
<ImageView
android:id="@+id/iv_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="@drawable/delete"
android:padding="5dp" />
</RelativeLayout>
演示運行看看效果
設置輸入框的寬為200dip
<EditText
android:id="@+id/et_input"
android:paddingRight="40dip"
android:layout_marginTop="20dip"
android:layout_centerHorizontal="true"
android:layout_width="200dip"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
解決按下變白的問題:
listView = new ListView(this); listView.setBackgroundResource(R.drawable.listview_background); listView.setAdapter(new MyAdapter());
解決點擊popupwindow外部,無法消掉問題
popupWindow.setOutsideTouchable(true);
設置選擇某一條,並且顯示在輸入框中
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
et_input.setText(msgList.get(position));
}
});
注意需要設置popupwindow的焦點才起作用
popupWindow.setFocusable(true);
在setOnItemClickListener方法中消掉對話框
popupWindow.dismiss();
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_down_arrow://點擊向下箭頭
if(window == null){
window = new PopupWindow(this);
// window.setBackgroundDrawable(new ColorDrawable(color.transparent));
window.setWidth(et_input.getWidth());
window.setHeight(200);
//TODO 設置popupWindow的內容
window.setContentView(contentView);
// window.setOutsideTouchable(true);
//不一定要背景,主要是setFocusable要先執行,showAsDropDown後執行
window.setFocusable(true);
}
window.showAsDropDown(et_input, 0, 0);
break;
default:
break;
}
}
繼承已有View實現自定義View
通過對android原生控件的研究,可以發現android中的控件都是繼承view類,如textView、ImageView等,通過重寫相關的方法來實現新的效果,通過這個我們得到兩點:
我們可以在已有控件的基礎上,通過重寫相關方法來實現我們的需求。
繼承view類或viewgroup類,來創建我們所需要的控件。一般來講,通過繼承已有的控件,來自定義控件要簡單一點。


開關按鈕,包名:com.itheima.togglebutton,並把圖片拷貝到工程中
實現三個構造方法
/**
* 自定按鈕
* @author afu
*/
public class MyToggleButton extends View {
// 增加一個默認顯示樣式時候使用
public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
// 在布局文件中聲明view的時候,該方法有系統調用
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 在代碼中new實例化時調用
public MyToggleButton(Context context) {
super(context);
}
}
在布局文件中使用
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.itheima.togglebutton.MyToggleButton
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
1.執行view構造方法,創建對象
2.測量view大小
onMeasure(int,int);來完成測量動作
3.指定view的位置,子View只有建議權,父View才有決定權;
onLayout(boolean,int,int,int ,int);
這個方法一般用不著,如果自定義繼承ViewGoup才用到
4.繪制view的內容
onDraw(canvas);
package com.bokeyuan.togglebutton;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
/**
* 自定按鈕
* @author m
*/
public class MyToggleButton extends View {
/**
* 一個View從創建到顯示屏幕上的主要步驟:
* 1.執行view構造方法,創建對象
* 2.測量view大小
* onMeasure(int,int);來完成測量動作
* 3.指定view的位置,子View只有建議權,父View才有決定權;
* onLayout(boolean,int,int,int ,int);
* 這個方法一般用不著,如果自定義ViewGoup才用到
* 4.繪制view的內容
* onDraw(canvas);
*
*/
private Paint paint;
/**
* 測量
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//設置當前view的測量大小
setMeasuredDimension(100, 100);
}
/**
* 繪制
*/
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
//繪制顏色,可以理解成背景顏色
canvas.drawColor(Color.RED);
//繪制圓形
canvas.drawCircle(50, 50, 20, paint);
}
private void init(Context context) {
paint = new Paint();
paint.setColor(Color.GREEN);
//設置抗鋸齒,讓邊緣圓滑,一般都會設置
paint.setAntiAlias(true);
}
// 增加一個默認顯示樣式時候使用
public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
// 在布局文件中聲明view的時候,該方法有系統調用
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
// 在代碼中new實例化時調用
public MyToggleButton(Context context) {
super(context);
init(context);
}
}
package com.bokeyuan.togglebutton;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
/**
* 自定按鈕
* @author m
*/
public class MyToggleButton extends View {
/**
* 一個View從創建到顯示屏幕上的主要步驟:
* 1.執行view構造方法,創建對象
* 2.測量view大小
* onMeasure(int,int);來完成測量動作
* 3.指定view的位置,子View只有建議權,父View才有決定權;
* onLayout(boolean,int,int,int ,int);
* 這個方法一般用不著,如果自定義ViewGoup才用到
* 4.繪制view的內容
* onDraw(canvas);
*
*/
private Paint paint;
private Bitmap backGroundBitmap;
private Bitmap slideBitmap;
private Context context;
/**
* 測量
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//設置當前view的測量大小
setMeasuredDimension(backGroundBitmap.getWidth(), backGroundBitmap.getHeight());
}
/**
* 繪制
*/
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
//繪制顏色,可以理解成背景顏色
// canvas.drawColor(Color.RED);
//繪制圓形
// canvas.drawCircle(50, 50, 20, paint);
canvas.drawBitmap(backGroundBitmap, 0, 0, paint);
}
private void init(Context context) {
this.context = context;
paint = new Paint();
paint.setColor(Color.GREEN);
//設置抗鋸齒,讓邊緣圓滑,一般都會設置
paint.setAntiAlias(true);
//初始化圖片-從資源文件中解析成Bitmap對象
slideBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
backGroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
}
// 增加一個默認顯示樣式時候使用
public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
// 在布局文件中聲明view的時候,該方法有系統調用
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
// 在代碼中new實例化時調用
public MyToggleButton(Context context) {
super(context);
init(context);
}
}
canvas.drawBitmap(slideBitmap, 45, 0, paint);
分別設置0和30運行看看效果
package com.bokeyuan.togglebutton;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
/**
* 自定按鈕
* @author m
*/
public class MyToggleButton extends View implements View.OnClickListener {
/**
* 一個View從創建到顯示屏幕上的主要步驟:
* 1.執行view構造方法,創建對象
* 2.測量view大小
* onMeasure(int,int);來完成測量動作
* 3.指定view的位置,子View只有建議權,父View才有決定權;
* onLayout(boolean,int,int,int ,int);
* 這個方法一般用不著,如果自定義ViewGoup才用到
* 4.繪制view的內容
* onDraw(canvas);
*
*/
private Paint paint;
private Bitmap backGroundBitmap;
private Bitmap slideBitmap;
private Context context;
/**
* 距離左邊的距離
*/
private float slideLeft;
/**
* 判斷當前開關狀態
* true為開
* false為關
*/
private boolean curStata = false;
/**
* 測量
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//設置當前view的測量大小
setMeasuredDimension(backGroundBitmap.getWidth(), backGroundBitmap.getHeight());
}
/**
* 繪制
*/
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
//繪制顏色,可以理解成背景顏色
// canvas.drawColor(Color.RED);
//繪制圓形
// canvas.drawCircle(50, 50, 20, paint);
canvas.drawBitmap(backGroundBitmap, 0, 0, paint);
//繪制滑動按鈕
canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
}
private void init(Context context) {
this.context = context;
paint = new Paint();
paint.setColor(Color.GREEN);
//設置抗鋸齒,讓邊緣圓滑,一般都會設置
paint.setAntiAlias(true);
//初始化圖片-從資源文件中解析成Bitmap對象
slideBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);-
backGroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
setOnClickListener( MyToggleButton.this);
}
// 增加一個默認顯示樣式時候使用
public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
// 在布局文件中聲明view的時候,該方法有系統調用
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
// 在代碼中new實例化時調用
public MyToggleButton(Context context) {
super(context);
init(context);
}
@Override
public void onClick(View v) {
curStata = !curStata;
flushState();
}
/**
* 刷新狀態
*/
private void flushState() {
//設置距離左邊的距離
if(curStata){
slideLeft = backGroundBitmap.getWidth()-slideBitmap.getWidth();
}else{
slideLeft = 0;
}
/**
* 刷新View,會導致當前View的onDraw方法執行
*/
invalidate();
}
}
實現思想,參照手機衛士中的拖動的原理
/**
* 第一次按下的x坐標
*/
int startX = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN://按下
//1.記錄第一次按下坐標
startX = (int) event.getRawX();
break;
case MotionEvent.ACTION_MOVE://滑動
//2.來到新的坐標
int newX = (int) event.getRawX();
//3.計算偏移量
int dX = newX - startX;
slideLeft += dX;
//4.更新UI-onDraw方法即可--invalidate();
invalidate();
//5.重新記錄坐標
startX = (int) event.getRawX();
break;
case MotionEvent.ACTION_UP://離開
break;
default:
break;
}
return true;
}
public class MyToggleButton extends View implements OnClickListener {
private Paint paint;
/**
* 一個View從創建到顯示到屏幕過程中的步驟: 1.執行View的構造方法,實例化;通常在構造方法裡面加載資源 2.測量view對象
* onMeasure(int,int) 3.指定View的位置 - 一般的View用不到,自定義包括其他View進來這樣的控才用到
* onLayout(boolean,int,int,int,int) 4.繪制View對象 onDraw(canvas)
*
*/
private Bitmap backgroundBitmap;
private Bitmap slideBitmap;
/**
* 滑動圖片,距離左邊的距離
*/
private float slideLeft;
/**
* 按鈕的狀態 false為關閉 true為開
*/
private boolean curState = false;
// 測量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 設置測量值
setMeasuredDimension(backgroundBitmap.getWidth(),
backgroundBitmap.getHeight());
}
// 繪制
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// canvas.drawColor(Color.GREEN);
// canvas.drawCircle(50, 50, 20, paint);
canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
}
/**
* 第一次按下的x坐標
*/
int startX = 0;
int maxLeft;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN://按下
//1.記錄第一次按下坐標
startX = (int) event.getRawX();
break;
case MotionEvent.ACTION_MOVE://滑動
//2.來到新的坐標
int newX = (int) event.getRawX();
//3.計算偏移量
int dX = newX - startX;
slideLeft += dX;
//4.更新UI-onDraw方法即可--invalidate();
flushView();
//5.重新記錄坐標
startX = (int) event.getRawX();
break;
case MotionEvent.ACTION_UP://離開
break;
default:
break;
}
return true;
}
// 刷新View的狀態,並且糾正非法滑動
private void flushView() {
if(slideLeft < 0){
slideLeft = 0;
}
if(slideLeft > maxLeft){
slideLeft = maxLeft;
}
//屏蔽非法滑動
invalidate();
}
private void init(Context context) {
paint = new Paint();
paint.setColor(Color.RED);
// 設置抗鋸齒-使其變得光滑
paint.setAntiAlias(true);
// 加載資源圖片
backgroundBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_background);
slideBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.slide_button);
//滑動圖片距離左邊的距離
maxLeft = backgroundBitmap.getWidth()-slideBitmap.getWidth();
// 設置點擊事件
// setOnClickListener(this);
}
// 一般會在代碼中實例化
public MyToggleButton(Context context) {
super(context);
init(context);
}
// 帶有兩個參數的構造方法,在布局文件中使用的時候,就會回調
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
// 我們需要設置默認的樣式風格的時候
public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
@Override
public void onClick(View v) {
curState = !curState;
flushState();
}
// 刷新View的狀態
private void flushState() {
if (curState) {
slideLeft = maxLeft;
} else {
slideLeft = 0;
}
flushView();
}
}
先畫圖分析

代碼如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN://按下
//1.記錄第一次按下坐標
startX = (int) event.getRawX();
break;
case MotionEvent.ACTION_MOVE://滑動
//2.來到新的坐標
int newX = (int) event.getRawX();
//3.計算偏移量
int dX = newX - startX;
slideLeft += dX;
//4.更新UI-onDraw方法即可--invalidate();
flushView();
//5.重新記錄坐標
startX = (int) event.getRawX();
break;
case MotionEvent.ACTION_UP://離開
/**
* 當UP事件發生的時候,由按鈕的左邊距離(btn_left)確定View的狀態;
當btn_left >= maxLeft/2 設置為開狀態
當btn_left < maxLeft/2 設置為 關閉狀態
*/
if(slideLeft >= maxLeft/2){
curState = true;
}else{
curState = false;
}
flushState();
break;
default:
break;
}
return true;
}
恢復點擊事件
演示會有bug
public class MyToggleButton extends View implements OnClickListener {
private Paint paint;
/**
* 一個View從創建到顯示到屏幕過程中的步驟: 1.執行View的構造方法,實例化;通常在構造方法裡面加載資源 2.測量view對象
* onMeasure(int,int) 3.指定View的位置 - 一般的View用不到,自定義包括其他View進來這樣的控才用到
* onLayout(boolean,int,int,int,int) 4.繪制View對象 onDraw(canvas)
*
*/
private Bitmap backgroundBitmap;
private Bitmap slideBitmap;
/**
* 滑動圖片,距離左邊的距離
*/
private float slideLeft;
/**
* 按鈕的狀態 false為關閉 true為開
*/
private boolean curState = false;
// 測量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 設置測量值
setMeasuredDimension(backgroundBitmap.getWidth(),
backgroundBitmap.getHeight());
}
// 繪制
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// canvas.drawColor(Color.GREEN);
// canvas.drawCircle(50, 50, 20, paint);
canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
}
/**
* 第一次按下的x坐標
*/
int startX = 0;
/**
* 最初的歷史位置
*/
int lastX = 0;
/**
* 滑動按鈕距離左邊的最大距離
*/
int maxLeft;
/**
* 點擊事件是否可用
* true 可用
* false 不可用
*/
boolean isClickEnable = true;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN://按下
//1.記錄第一次按下坐標
lastX = startX = (int) event.getRawX();
isClickEnable = true;
break;
case MotionEvent.ACTION_MOVE://滑動
//2.來到新的坐標
int newX = (int) event.getRawX();
//3.計算偏移量
int dX = newX - startX;
slideLeft += dX;
//4.更新UI-onDraw方法即可--invalidate();
if(Math.abs(event.getRawX()-lastX)>5){
isClickEnable = false;
}
flushView();
//5.重新記錄坐標
startX = (int) event.getRawX();
break;
case MotionEvent.ACTION_UP://離開
if(!isClickEnable){
/**
* 當UP事件發生的時候,由按鈕的左邊距離(btn_left)確定View的狀態;
當btn_left >= maxLeft/2 設置為開狀態
當btn_left < maxLeft/2 設置為 關閉狀態
*/
if(slideLeft >= maxLeft/2){
curState = true;
}else{
curState = false;
}
flushState();
}
break;
default:
break;
}
return true;
}
// 刷新View的狀態,並且糾正非法滑動
private void flushView() {
if(slideLeft < 0){
slideLeft = 0;
}
if(slideLeft > maxLeft){
slideLeft = maxLeft;
}
//屏蔽非法滑動
invalidate();
}
private void init(Context context) {
paint = new Paint();
paint.setColor(Color.RED);
// 設置抗鋸齒-使其變得光滑
paint.setAntiAlias(true);
// 加載資源圖片
backgroundBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_background);
slideBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.slide_button);
//滑動圖片距離左邊的距離
maxLeft = backgroundBitmap.getWidth()-slideBitmap.getWidth();
// 設置點擊事件
setOnClickListener(this);
}
// 一般會在代碼中實例化
public MyToggleButton(Context context) {
super(context);
init(context);
}
// 帶有兩個參數的構造方法,在布局文件中使用的時候,就會回調
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
// 我們需要設置默認的樣式風格的時候
public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
@Override
public void onClick(View v) {
if(isClickEnable){
curState = !curState;
flushState();
}
}
// 刷新View的狀態
private void flushState() {
if (curState) {
slideLeft = maxLeft;
} else {
slideLeft = 0;
}
flushView();
}
}
在android中使用SQLite數據庫
在android中使用SQLite數據庫 SQLite數據庫以其輕量、體積小等特點,使其在開發中運用的非常廣泛,在前面的博客中我也介紹過在Cocos2d-x中使用SQ
sqlite的基本使用,sqlite使用
sqlite的基本使用,sqlite使用一:基本操作 1繼承SQLiteOpenHelper public class UserSqliteOpenHel
Android之genymotion模擬器安裝於配置,androidgenymotion
Android之genymotion模擬器安裝於配置,androidgenymotion 今天是雙休日,可憐沒人陪,只好一個人玩電腦了,之前別人一直給我推薦genymo
手把手帶你畫一個 時尚儀表盤 Android 自定義View
手把手帶你畫一個 時尚儀表盤 Android 自定義View 拿到美工效果圖,咱們程序員就得畫得一模一樣。 為了不被老板噴,只能多練啊。 聽說你覺得前面幾篇都so eas