先上效果图:
这个工程并不难,但是零碎的知识点还是挺多的,下面来讲讲思路:
首先从 NumberPicker 开始:
public class CustomNumberPicker extends NumberPicker {
public CustomNumberPicker(Context context) {
super(context);
}
public CustomNumberPicker(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void addView(View child) {
super.addView(child);
updateView(child);
}
@Override
public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {
super.addView(child, index, params);
updateView(child);
}
@Override
public void addView(View child, android.view.ViewGroup.LayoutParams params) {
super.addView(child, params);
updateView(child);
}
public void updateView(View view) {
if (view instanceof EditText) {
// 文字颜色、大小
((EditText) view).setTextColor(ContextCompat.getColor(getContext(), R.color.numberpicker_text));
((EditText) view).setTextSize(20f);
}
}
}
这里是对原生 NumberPicker 的修改,所以直接继承 NumberPicker 并获取它的视图 view ,并利用 instanceof 筛选出 EditText ,修
改 EditText 的文字颜色和文字大小,即可改变 NumberPicker 文字的颜色和大小。
接下来是修改分割线颜色,这里先需要对 NumberPicker 进行初始化,然后利用反射获取到分割线的属性,再对其修改颜色:
/**
* 初始化滚动框布局
*/
private void initNumberPicker() {
workingAge_view = LayoutInflater.from(this).inflate(R.layout.popupwindow, null);
submit_workingAge = (Button) workingAge_view.findViewById(R.id.submit_workingAge);
numberPicker = (NumberPicker) workingAge_view.findViewById(R.id.numberPicker);
numberPicker.setMaxValue(50);
numberPicker.setMinValue(0);
numberPicker.setFocusable(false);
numberPicker.setFocusableInTouchMode(false);
numberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); // 关闭编辑模式
setNumberPickerDividerColor(numberPicker);
}
/**
* 自定义滚动框分隔线颜色
*/
private void setNumberPickerDividerColor(NumberPicker number) {
Field[] pickerFields = NumberPicker.class.getDeclaredFields();
for (Field pf : pickerFields) {
if (pf.getName().equals("mSelectionDivider")) {
pf.setAccessible(true);
try {
//设置分割线的颜色值
pf.set(number, new ColorDrawable(ContextCompat.getColor(this, R.color.numberpicker_line)));
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
DatePicker 也可以按照这种方法修改显示效果,这里再稍微提一下多个 NumberPicker 的联动效果的实现思路,比如省市区的选
择,假设数据来自服务器,在视图加载的时候,先获取到省的数据,通过 setDisplayedValues 显示数据,然后给省设置监听
setValueChangedListener ,当省的值发生变化时,获取到当前值并向服务器请求相应省里面市的数据,获得返回的市的数据后再加
载市的视图,接下来区的显示也是同理。
到这一步,对原生 NumberPicker 的修改就结束了,在这里我们用到了 PopupWindow 的布局文件,接下来就开始说一说
PopupWindow 和补间动画,首先看看布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/popupwindow_style"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.liuwan.numberpicker.widget.CustomNumberPicker
android:id="@+id/numberPicker"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginStart="15dp"
android:layout_toEndOf="@+id/numberPicker"
android:text="年"
android:textColor="@color/year"
android:textSize="18sp" />
</RelativeLayout>
<Button
android:id="@+id/submit_workingAge"
style="?android:attr/borderlessButtonStyle"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:background="@color/button_background"
android:gravity="center"
android:text="确定"
android:textColor="@color/button_text"
android:textSize="17sp" />
</LinearLayout>
在 PopupWindow 的布局文件中,我们使用了修改后的 NumberPicker,这里没有什么难点,就不多说了,其中还涉及到一个
PopupWindow 的样式文件:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 设置背景透明度和颜色 -->
<solid android:color="@color/popupwindow_background" />
<!-- 设置圆角 -->
<corners
android:topLeftRadius="5dp"
android:topRightRadius="5dp" />
</shape>
这里就设置了背景颜色和透明度,以及顶部圆角。
PopupWindow 的布局到这里就完成了,接下来是代码调用,因为在这里需要设置补间动画,所以先说一下补间动画的编写。
关于补间动画,可以参考我的另一篇博文《Android 补间动画的简单介绍及使用》,这里有两个动画,一个是弹出动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="400"
android:fromYDelta="100%p"
android:toYDelta="0" />
<alpha
android:duration="400"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
一个是退出动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="400"
android:fromYDelta="0"
android:toYDelta="50%p" />
<alpha
android:duration="400"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
在代码中设置通过点击相应控件弹出 PopupWindow ,并设置相关属性:
// 选择服务年限
edWorkingAge.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 设置初始值
numberPicker.setValue(workingAge);
// 强制隐藏键盘
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
// 填充布局并设置弹出窗体的宽,高
popupWindow = new PopupWindow(workingAge_view,
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// 设置弹出窗体可点击
popupWindow.setFocusable(true);
// 设置弹出窗体动画效果
popupWindow.setAnimationStyle(R.style.AnimBottom);
// 触屏位置如果在选择框外面则销毁弹出框
popupWindow.setOutsideTouchable(true);
// 设置弹出窗体的背景
popupWindow.setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
popupWindow.showAtLocation(workingAge_view,
Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
// 设置背景透明度
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 0.5f;
getWindow().setAttributes(lp);
// 添加窗口关闭事件
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 1f;
getWindow().setAttributes(lp);
}
});
}
});
这里对动画效果的设置是通过 style 属性控制的,在 res/values/styles.xml 中定义:
<!-- 自定义popupWindow_WorkingAge -->
<style name="AnimBottom" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/popupwindow_enter_anim</item>
<item name="android:windowExitAnimation">@anim/popupwindow_exit_anim</item>
</style>
到这里,基本上就完成了想要达到的效果,一些颜色的设置都定义在 colors.xml 文件中。