Android自定义控件的使用与PopupWindow

一、自定义控件需求

很多时候Android中的标准控件都不能满足我们的需求,所以我们会经常需要使用自定义的控件。接下来是一个简单的使用自定义控件的步骤。 ## 二、使用步骤

1、创建自定义的布局文件

首先,我们需要根据自己的需求,定义一个XML布局文件以定义我们自己想要的控件。代码如下(mybtn.xml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<xml version="1.0" encoding="utf-8">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="#000000" />
</LinearLayout>

2、创建一个自定义控件的类

根据我们自定义的布局文件,我们创建一个继承自LinearLayout的自定义类。在这个类中,通过导入上面的布局文件,找到相应的控件,并可以自定义一些方法对相应的控件操作。代码如下(MyLButton.java):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class MyLButton extends LinearLayout {
private static final String TAG = "MyLButton";
private ImageView imageView;
private TextView textView;
public MyLButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyLButton(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
// TODO Auto-generated constructor stub
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.mybtn, this);
imageView = (ImageView) view.findViewById(R.id.imageView1);
textView = (TextView) view.findViewById(R.id.textView1);
/**
* 注意:当我们使用多个这个自定义控件时,系统会为其分别分配内存空间
* 如下面在日志中打印textview控件的内存信息
*/
Log.d(TAG, "MyLButton()-->" + textView);//打印内存地址
}
/**
* 自定义的方法操作对应的控件
*/
//设置显示的图片
public void setImageResource(int resId) {
imageView.setImageResource(resId);
}
// 设置显示的文字
public void setTextViewText(String text) {
textView.setText(text);
}
}

3、在自己的布局文件中使用该自定义控件

在这里,我们只需要在自己要使用该自定义控件的地方引入该自定义控件所在的类,如com.example.mybutton.MyLButton。代码如下(activity_main.xml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.mybutton.MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<!--引用自定义控件-->
<com.example.mybutton.MyLButton
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.example.mybutton.MyLButton
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

4、使用我们的自定义控件

最后我们就只需要找到布局文件中使用的自定义控件,使用它。代码如下(MainActivity.java):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class MainActivity extends Activity {
private MyLButton myLButton1;
private MyLButton myLButton2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myLButton1 = (MyLButton) this.findViewById(R.id.btn1);
myLButton2 = (MyLButton) this.findViewById(R.id.btn2);
myLButton1.setTextViewText("SqliteStudio");
myLButton2.setTextViewText("Eclipse");
myLButton1.setImageResource(R.drawable.p1);
myLButton2.setImageResource(R.drawable.p2);
myLButton1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "Hello,SqliteStudio", Toast.LENGTH_SHORT).show();
}
});
myLButton2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "Hello,Eclipse", Toast.LENGTH_SHORT).show();
}
});
}
}

三、PopupWindow 介绍

popup window that can be used to display an arbitrary view. The popup window is a floating container that appears on top of the current activity.翻译大概就是:一个popup window可以用来展示任意的view。  popup window是一个出现在当前activity上面的浮动的容器。所以在Android UI开发中,经常需要在一个页面上显示好看的自定义菜单,或者弹出类似网页上JS效果的登录对话框等酷炫效果,此时我们可以利用PopupWindow来完成我们想实现的功能。

四、使用步骤

1、直接使用。代码如下:

1
2
3
4
5
6
7
8
9
PopupWindow popupWindow = new PopupWindow();
//设置要popupWindow的view
popupWindow.setContentView(View view);
//设置宽度
popupWindow.setWidth(LayoutParams.MATCH_PARENT);
//设置高度
popupWindow.setHeight(LayoutParams.MATCH_PARENT);
//设置该popupwWindow显示在view的左下角位置
popupWindow.showAsDropDown(View view);

2、自定义使用。

a、首先,定义自己的视图的xml文件。代码如下(popup_dialog.xml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pop_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</LinearLayout>
<Button
android:id="@+id/btn_take_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="20dip"
android:background="#aaaaaa"
android:text="拍照"
android:textStyle="bold" />
<Button
android:id="@+id/btn_pick_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="5dip"
android:background="#aaaaaa"
android:text="从相册选择"
android:textStyle="bold" />
<Button
android:id="@+id/btn_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dip"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="5dip"
android:background="#666666"
android:text="取消"
android:textColor="#ffffff"
android:textStyle="bold" />
</LinearLayout>

b、继承PopupWindow类,自定义自己的PopupWindow类。代码如下(MyPopupWindow.java):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class MyPopupWindow extends PopupWindow {
private Button btnTakePhoto, btnPickPhoto, btnCancel;
private View mMenuView;
public MyPopupWindow(Context context, OnClickListener onClickItem){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//关联布局文件
mMenuView = inflater.inflate(R.layout.popup_dialog, null);
btnTakePhoto = (Button) mMenuView.findViewById(R.id.btn_take_photo);
btnPickPhoto = (Button) mMenuView.findViewById(R.id.btn_pick_photo);
btnCancel = (Button) mMenuView.findViewById(R.id.btn_cancel);
btnTakePhoto.setOnClickListener(onClickItem);
btnPickPhoto.setOnClickListener(onClickItem);
btnCancel.setOnClickListener(onClickItem);
//设置PopupWindow的View
this.setContentView(mMenuView);
//设置PopupWindow弹出窗体的宽
this.setWidth(LayoutParams.MATCH_PARENT);
//设置PopupWindow弹出窗体的高
this.setHeight(LayoutParams.MATCH_PARENT);
//设置PopupWindow弹出窗体可点击
this.setFocusable(true);
//设置PopupWindow弹出窗体动画效果
this.setAnimationStyle(R.style.PopupAnimation);
//实例化一个ColorDrawable颜色为半透明
ColorDrawable bgColor = new ColorDrawable(0xb0000000);
//设置PopupWindow弹出窗体的背景
this.setBackgroundDrawable(bgColor);
//mMenuView添加OnTouchListener监听判断获取触屏位置如果在选择框外面则销毁弹出框
mMenuView.setOnTouchListener(new MenuItemOnTouchListener());
}
//触摸在popupWindow上方则取消显示
private class MenuItemOnTouchListener implements OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
int height = mMenuView.findViewById(R.id.pop_layout).getTop();
int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_UP) {
if (y < height) {
dismiss();
}
}
return true;
}
}
}

其中动画代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!--style.xml-->
<style name="PopupAnimation" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
<item name="android:windowExitAnimation">@anim/push_bottom_out</item>
</style>
<!--push_bottom_in.xml-->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >v
<translate
android:duration="200"
android:fromYDelta="100%p"
android:toYDelta="0" />
<alpha
android:duration="500"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
<!--push_bottom_out.xml-->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromYDelta="0"
android:toYDelta="100%p" />
<alpha
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>

c、使用自定义的PopupWindow。

1
2
3
4
5
6
7
8
9
10
MyPopupWindow popupWindow = new MyPopupWindow(this, new ItemOnClickListener());
/**
* 设置layout在PopupWindow中显示的位置
* showAtLocation(View parent, int gravity, int x, int y)
* @param parent PopupWindow要显示的父View
* @param gravity 位置
* @param x X坐标
* @param y Y坐标
*/
popupWindow.showAtLocation(MainActivity.this.findViewById(R.id.main), Gravity.CENTER_HORIZONTAL, 0, 0);