一、PickerView
1、PickerView是什么
仿iOS的PickerView控件,带有3D圆弧效果,并封装了时间选择和选项选择这两种选择器。
WheelView —— 基础控件
带有3D圆弧效果。
支持文字、颜色、大小设置。
支持背景颜色设置。
支持item的分隔线设置。
支持item间距设置。
支持设置是否循环。
OptionsPickerView —— 选项选择器
支持一、二、三级联动数据。
支持一、二、三级不联动数据。
支持自定义布局。
支持自定义标题栏。
支持“省,市,区”等选项的单位(label)显示、隐藏和自定义。
支持dialog 模式显示。
支持自定义设置容器。
支持实时回调监听。
联动数据支持切换Item时,还原为第一项。
TimePickerView —— 时间选择器
支持选择年、月、日的范围。
支持年月日时分秒显示。
支持设置当前默认时间。
支持自定义布局。
支持自定义标题栏。
支持“年,月,日,时,分,秒”等选项的单位(label)显示、隐藏和自定义。
支持dialog 模式显示。
支持自定义设置容器。
支持实时回调监听。
2、使用方式
1.WheelView的使用
依赖
compile 'com.contrarywind:Android-PickerView:4.1.9'
layout中配置
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.contrarywind.view.WheelView
android:id="@+id/wheel_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
代码
public class MainActivity extends AppCompatActivity {
private WheelView mWheelView;
private ArrayWheelAdapter<String> mMyAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWheelView = findViewById(R.id.wheel_view);
mWheelView.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(int index) {
Log.i("Simon", "onItemSelected index: " + index);
}
});
List<String> list = new ArrayList<>();
list.add("我的中国心");
list.add("北国之春");
list.add("鹿港小镇");
mMyAdapter = new ArrayWheelAdapter(list);
mWheelView.setAdapter(mMyAdapter);
}
}
效果图
图片.png
注意:
OnItemSelectedListener中回调被选中的值
mWheelView.getCurrentItem()得到当前选中的值
2.TimePickerView的使用
private void showTimePickerView() {
TimePickerView pvTime = new TimePickerBuilder(MainActivity.this, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
Toast.makeText(MainActivity.this, date.toString(), Toast.LENGTH_SHORT).show();
}
}).build();
pvTime.show();//显示时间选择器
}
效果图
图片.png
3.级联选择
private void initOptionPicker() {
List<String> options1Items = new ArrayList<>();
options1Items.add("射雕英雄传");
options1Items.add("神雕侠侣");
options1Items.add("鹿鼎记");
List<String> options2Items_01 = new ArrayList<>();
options2Items_01.add("郭靖");
options2Items_01.add("黄蓉");
options2Items_01.add("杨铁心");
options2Items_01.add("欧阳克");
List<String> options2Items_02 = new ArrayList<>();
options2Items_02.add("小龙女");
options2Items_02.add("杨过");
options2Items_02.add("大雕");
List<String> options2Items_03 = new ArrayList<>();
options2Items_03.add("小柜子");
options2Items_03.add("康熙");
options2Items_03.add("康亲王");
options2Items_03.add("鳌拜");
List<List<String>> options2Items = new ArrayList<>();
options2Items.add(options2Items_01);
options2Items.add(options2Items_02);
options2Items.add(options2Items_03);
OptionsPickerView optionsPickerView = new OptionsPickerBuilder(this, new OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int options2, int options3, View v) {
String tx = options1Items.get(options1)
+ options2Items.get(options1).get(options2);
Toast.makeText(getBaseContext(), tx, Toast.LENGTH_SHORT).show();
}
})
.setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() {
@Override
public void onOptionsSelectChanged(int options1, int options2, int options3) {
String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3;
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
})
.build();
optionsPickerView.setPicker(options1Items, options2Items);
optionsPickerView.show();
}
效果图
图片.png
二、AndroidAutoSize
1、dp,sp转px
px:像素
dp:虚拟像素,在不同的像素密度的设备上会自动适配
dip:同dp
sp:同dp相似,用于字体,会根据用户的字体大小偏好来缩放
public class DisplayUtils {
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dp2px(Context context, int dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dp(Context context, int pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*/
public static int sp2px(Context context, int spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* 将px值转换为sp值,保证文字大小不变
*/
public static int px2sp(Context context, int pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* dp转为px
* @param context
* @param dp
* @return
*/
public static int dp2px_2(Context context, int dp) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, dp,
context.getResources().getDisplayMetrics());
}
/**
* sp转为px
* @param context
* @param sp
* @return
*/
public static int sp2px_2(Context context, int sp) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, sp,
context.getResources().getDisplayMetrics());
}
}
2、UI自动适配框架配置以及使用
AutoLayout(已废弃,不建议使用)
[停止维护]Android屏幕适配方案,直接填写设计图上的像素尺寸即可完成适配,最大限度解决适配问题。
https://github.com/hongyangAndroid/AndroidAutoLayout
AndroidAotuSize
A low-cost Android screen adaptation solution (今日头条屏幕适配方案终极版,一个极低成本的 Android 屏幕适配方案).
https://github.com/JessYanCoding/AndroidAutoSize
1.依赖
implementation 'me.jessyan:autosize:1.2.1'
2.在 AndroidManifest 中填写全局设计图尺寸 (单位 dp)
<manifest>
<application>
<meta-data
android:name="design_width_in_dp"
android:value="360"/>
<meta-data
android:name="design_height_in_dp"
android:value="640"/>
</application>
</manifest>
3.进阶使用
1、某页面不是按照设计图设计的,如何处理
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {
/**
* 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选择一个作为基准进行适配)
*
* @return {@code true} 为按照宽度进行适配, {@code false} 为按照高度进行适配
*/
@Override
public boolean isBaseOnWidth() {
return false;
}
/**
* 设计图尺寸为 1080px * 1920px, 高换算成 dp 为 960 (1920px / 2 = 960dp)
* <p>
* 返回的设计尺寸, 单位 dp
* {@link #getSizeInDp} 须配合 {@link #isBaseOnWidth()} 使用, 规则如下:
* 如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 则应该返回设计图的总宽度
* 如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 则应该返回设计图的总高度
* 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, {@link #getSizeInDp} 则返回 {@code 0}
*
* @return 单位 dp
*/
@Override
public float getSizeInDp() {
return 667;
}}
2、某页面想放弃适配,需要实现CancelAdapt
3、想支持Fragment
Application初始化的时候执行:
AutoSizeConfig.getInstance().setCustomFragment(true);
然后Fragment实现CustomAdap或者CancelAdapt
4、万能解决方案
在任何情况下本来适配正常的布局突然出现适配失效,适配异常等问题,只要重写 Activity 的 getResources() 方法即可,如果是 Dialog、PopupWindow 等控件出现适配失效或适配异常,同样在每次 show() 之前调用 AutoSize#autoConvertDensity() 即可。
@Override
public Resources getResources() {
//需要升级到 v1.1.2 及以上版本才能使用 AutoSizeCompat
AutoSizeCompat.autoConvertDensityOfGlobal((super.getResources());//如果没有自定义需求用这个方法
AutoSizeCompat.autoConvertDensity((super.getResources(), 667, false);//如果有自定义需求就用这个方法
return super.getResources();
}
5、配置
AutoSizeConfig.getInstance()
//是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
//如果没有这个需求建议不开启
.setCustomFragment(true)
//是否屏蔽系统字体大小对 AndroidAutoSize 的影响, 如果为 true, App 内的字体的大小将不会跟随系统设置中字体大小的改变
//如果为 false, 则会跟随系统设置中字体大小的改变, 默认为 false
.setExcludeFontScale(true)
//区别于系统字体大小的放大比例, AndroidAutoSize 允许 APP 内部可以独立于系统字体大小之外,独自拥有全局调节 APP 字体大小的能力
//当然, 在 APP 内您必须使用 sp 来作为字体的单位, 否则此功能无效, 不设置或将此值设为 0 则取消此功能
.setPrivateFontScale(0.8f)
//屏幕适配监听器
.setOnAdaptListener(new onAdaptListener() {
@Override
public void onAdaptBefore(Object target, Activity activity) {
//使用以下代码, 可以解决横竖屏切换时的屏幕适配问题
//使用以下代码, 可支持 Android 的分屏或缩放模式, 但前提是在分屏或缩放模式下当用户改变您 App 的窗口大小时
//系统会重绘当前的页面, 经测试在某些机型, 某些情况下系统不会重绘当前页面, ScreenUtils.getScreenSize(activity) 的参数一定要不要传 Application!!!
// AutoSizeConfig.getInstance().setScreenWidth(ScreenUtils.getScreenSize(activity)[0]);
// AutoSizeConfig.getInstance().setScreenHeight(ScreenUtils.getScreenSize(activity)[1]);
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s onAdaptBefore!", target.getClass().getName()));
}
@Override
public void onAdaptAfter(Object target, Activity activity) {
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s onAdaptAfter!", target.getClass().getName()));
}
})
//是否打印 AutoSize 的内部日志, 默认为 true, 如果您不想 AutoSize 打印日志, 则请设置为 false
.setLog(false)
//是否使用设备的实际尺寸做适配, 默认为 false, 如果设置为 false, 在以屏幕高度为基准进行适配时
//AutoSize 会将屏幕总高度减去状态栏高度来做适配
//设置为 true 则使用设备的实际屏幕高度, 不会减去状态栏高度
//在全面屏或刘海屏幕设备中, 获取到的屏幕高度可能不包含状态栏高度, 所以在全面屏设备中不需要减去状态栏高度,所以可以 setUseDeviceSize(true)
.setUseDeviceSize(true)
//是否全局按照宽度进行等比例适配, 默认为 true, 如果设置为 false, AutoSize 会全局按照高度进行适配
.setBaseOnWidth(false)
//设置屏幕适配逻辑策略类, 一般不用设置, 使用框架默认的就好
.setAutoAdaptStrategy(new AutoAdaptStrategy())
;
网友评论