学习android一段时间了,这期间做了两个APP,一个天气预报应用,另一个是求职简历应用,遇到了许多困难,也学到了许多知识,在此记录下学习的经验以及遇到的问题。
JunzWeather:你的天气
JunzResume:你的简历
问题和心得
-
模糊查询
在你的天气这个项目中,有一个功能是切换城市,用到了模糊查询。
标准sql语句是这样的:
SELECT DISTINCT area_zh FROM city WHERE area_zh LIKE ‘%cityname%' OR area_en LIKE '%cityname%' ORDER BY area_en;
可以通过“cityname”在表中/英城市名数据列中查出城市名并排序。
程序代码中我最初是这么写的:
String sql = "SELECT DISTINCT area_zh FROM city WHERE area_zh LIKE '%?%' OR area_en LIKE '%?%' ORDER BY area_en;";
Cursor cursor = db.rawQuery(sql, new String[]{SearchText,SearchText});
无法正常使用,后改成下面代码能达到查询目的:
String sql = "SELECT DISTINCT area_zh FROM city WHERE area_zh LIKE ? OR area_en LIKE ? ORDER BY area_en;";
Cursor cursor = db.rawQuery(sql, new String[] { "%" + SearchText + "%","%" + SearchText + "%" });
由此看来在使用占位符?
进行模糊查询时,要将%
和?
看做一个整体,当做参数传入,如果仅仅把?
当做参数,%
写入sql字符串,会使此sql语句语义错误!
-
ListView更新数据
这两个项目中都使用了ListView,传入自定义的adapter显示数据。
但是调试时发现即使动态改变内部数据后,调用adapter.notifyDataSetChanged();
方法我列表的显示却没有变化!
当时我的更新数据方法是这样写的:
cityNameList = db.searchAllCityName();
adapter.notifyDataSetChanged();
这么看好像逻辑很正常啊,其实不然。
我们在将List传入到adapter之后,adapter保存了指向list对象的引用,用以显示其中数据。
但是代码cityNameList = db.searchAllCityName();
会让cityNameList
指向一个新的List对象,而adapter内部指向保存数据的对象未改变,而且由于cityNameList
引用的改变,我们也无法再访问到保存数据的List集合,所以无论如何操纵,显示的数据自然不会改变!
因此,正确的写法是:
cityNameList.clear();
cityNameList.addAll(db.searchAllCityName());
adapter.notifyDataSetChanged();
先将List清除,在把查询的加过全部加到List集合中,通知adapter更新数据。
-
APP启动关闭标题栏
在我们调试或者运行APP的时候,会发现在软件启动时会屏幕上方会短暂出现一个标题栏,非常影响视觉体验。那如何去掉这个bar呢?
最简单的方法就是打开项目的AndroidManifest.xml
找到android:theme
属性,将主题设置为Theme.NoTitleBar
,这样就不会出现启动时那个标题栏了。
-
背景选择器selector
当我们点击,按住一个控件,比如按钮时,有时我们会希望它的背景图片发生变化,这样可以使应用更人性化。这是就要用到了选择器。
选择器是以xml
文件放在res/drawable
文件夹下的,完成后在布局文件中的android:background="@drawable/xxx.xml"
属性引用该文件即可。比如在你的简历项目中,其中的按钮默认为白色,当点击或按住时则显示为黄色,写法如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_add_click" android:state_pressed="true"/>
<item android:drawable="@drawable/btn_add_click" android:state_focused="true"/>
<!-- 正常显示的样式放到最后,因为如果放到前面,就不加载后面的了!所以放到最后 -->
<item android:drawable="@drawable/btn_add_default" android:state_enabled="true"/>
</selector>
其中android:drawable
属性是你要现实的图片ID,android:state_pressed="true"
属性你你显示该图片的条件,比如这个就是在点击时切换背景图片为btn_add_click
。
有一点要注意,正常显示的itemandroid:state_enabled="true
必须要写在最后,不然无法正常达到显示效果,我最初就是遇到这个坑,找了好久才发现问题。
我个人猜测原因是在加载次xml文件时,加载到这一行就会停止加载,不再加载后面条目。
-
记住密码功能
你的简历项目中,实现了登录时记住密码功能。
该功能是借助SharedPreferences,在onStop()
方法里将账号密码存入xml文件里,当回到该Activity时,在onRame()
方法内取出存入的账号信息,达到记住密码功能。
注意:存储数据和清除数据都要执行commit()
命令。
-
TextView输入框不换行
在项目中使用TextView控件时,出现了输入文字超出输入框后不换行的现象,在网上查询答案设置android:singleLine="false"
等等属性也不起作用。
经过自己调试,终于发现是因为此控件在TableLayout
中,而且我设置了android:stretchColumns
属性来填充列,这就会使TextView换行出现问题,解决方法是去掉此属性或者再加上android:stretchColumns
属性。
-
Toast重复显示
Toast是经常使用的信息提示工具,当我们使用代码Toast.makeText(context, text, Toast.LENGTH_SHORT).show;
,每次触发都会弹出一条Toast,用户体验非常差,所以我们可以将其封装成一个公共方法,每次都是使用同一个Toasr,显示不同文本,解决该问题。
代码如下:
public static void showToast(Context context, String text) {
if (toast == null) {
toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
} else {
toast.setText(text);
}
toast.show();
}
这里需要传入一个context
,我发现其实只有第一次使用才会用到context
,以后调用用的都是第一次传入的,可以正常显示。
-
输入框弹出键盘类型
当我们做输入功能时,有时需要规定准备输入时弹出键盘的类型,这要用到android:inputType
属性,比如要输入电话就只能弹出数字键盘,则设置控件属性为android:inputType="number"
,这个属性有很多参数,可根据需求选择。
-
如何获取fragment中的控件
在你的简历这个项目中,使用了侧滑栏drawerlayout
,弹出侧滑栏点击具体表项,就可将对应的fragment
显示到主内容区。
那就需要获取到fragment
的控件进行操作。在fragment
中可以重载onCreateView
方法,其中有个LayoutInflater
参数,借助该参数调用.inflate(int resource, ViewGroup root, boolean attachToRoot)
方法就可以得到一个返回的view
。再借助方法view.findViewById(id)
获得控件。
关于那三个参数的作用可以看看这篇博客:inflate参数作用
<br /><br /><br /><br />
网友评论