android自定义控件无法显示的原因
编者:李国帅
背景:
Android开发中经常会遇到时间选择,而且经常会被要求使用类似ios的滚轮风格。只是android并不是ios,没有滚轮的时间选择器,那就需要进行定制,网上也有不少的开源定制View。一次,我在使用的时候,不知道改动了哪个地方,控件怎么也显示不出。
前后比较:
原本应该是这样的:
可是被改动之后,怎么也显示不出来
解决过程:
怎么回事呢?原来是好的,后来不行了,自己到底改动了什么?我的注意力被吸引在对比上,反反复复的比较原代码和新代码的差异,总是不觉得自己改了什么。
而且还有个问题,虽然不能显示控件,但是从logcat和console不能找到任何异常或错误日志,编译器也没有提示。
反复检测比较几次后搞得自己没脾气,这部分代码还是挺多的,难道自己有必要走读代码吗?
最后静下心,才发现,自己对出现的问题还是太急躁了,问题还是要从源头去分析。
问题的本质是控件的大小和可见性,时间段View的核心是WheelView,而WheelView被类WheelTime管理,WheelView中的数字TextView的字体大小在WheelView构造函数中定义,该字体大小又在TimePickerView构造函数中定义,继续向上追溯是由setContentSize函数定义。
错误的根源在于这么一句.setContentSize(px2sp(context, R.dimen.sp_17)),其中错误的使用了函数px2sp。
public static int px2sp(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / scale + 0.5f);
}
而正确的函数应该是
public static int px2sp(Context context, int id) {
float pxValue = context.getResources().getDimension(id);
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
在java中这种隐式的类型转换很难被发现,而且即便是真的有隐患,使用try…catch,只要不打印出来,依然难以从logcat或console找到线索。
这也是自己比较代码的时候,习惯性认为某些惯用函数是正确的,而忽视了某些非常见用法。而程序作为一个整体,单个函数的正确并不代表程序功能的正确。
总结:
解决后发现这个问题的本质并不复杂,但是花费了很长时间。
产生原因还是因为修改和移植没有注意细节。
解决时间过长是因为自己心中的执念。老是纠结于为什么原来可以现在怎么就不可以,而不是静下心来,聚焦于问题的源头,抓住问题的关键和本质。
我想,人生中还是有许多问题,并不是不能解决,而是自己愿不愿意下决心去解决。
与其纠结于那么多为什么,而不静下心一步步分析,一步步接近问题的真相,和我们期望的结果。