注:本文中的题目来自学校,仅供学习使用
11月25日起.正式开始复习(预习)Android编程
中间因为课程设计停了几个月,到今天为止终于结束了一轮复习
小小的记录一下一些注意点以及我第一遍犯的错
顺便掐个做题时间(创建项目往往就要1分种左右)
之后还会总结一篇核心的知识点的文章
Make an app with 2 components. The root layout is a LinearLayout. The 1st component shows your name and ID. The 2nd component a Button. Click the Button will show a Toast, which shows your name and ID.0
耗时: 3:52.482
To layout 3 TextViews in the RelativeLayout. The 1st TextView shows your name and ID and aligns in the center of the screen. The 2nd TextView shows your name and aligns in the left of the screen and below the 1st screen. The 3rd TextView aligns in the bottom and right of the screen.
除了最上面的两个,下面的都是相对于整个容器来说的
而最上面的两个可以通过指定id来寻找 相对位置
通常打Parent和below above等就会自动跳出来
Make an app with 3 components. The root layout is LinearLayout. The 1st one is a TextView shows your name and ID. It aligns in horizontal center of the first row. The 2nd one is a Button with 200dp width and aligns in the right of the 2nd row. The 3rd one is a Button with 200dp width and aligns in the left of the 3rd row, but the text in the Button aligns right.
The root layout is LinearLayout.
Add 3 EditTexts, 1 Button and 1 TextView to the LinearLayout
The Message EditText using layout_weight=“3”3) The TextView using layout_weight=“1”
All EditTexts have android:hint attribute to show the hint message for users
The TextView shows your name and student number
不要忘记hint这个属性就好了
layout_weight为各个组件设置权重
这里需要注意他均分的空间是去除组件所占空间的剩余空间(总的长度减去组件自身的长度)
而他究竟是设置在水平上还是垂直上由父组件的orientation属性来决定,所以有时候需要实现在水平方向上的均分,还需要新建一个线性布局,在它的里面放置想要均分空间的组件
The root layout is LinearLayout.
1 TextView in the first row, shows your name and student number;
3 CheckBoxes in the 2nd row;
1 TextView in the 3rd row, which shows the checked message when the checkboxes’s states are changed.
耗时: 14:15.391
耗时: 6:08.302
c1 = findViewById(R.id.t5_c1);
c1.setOnCheckedChangeListener
之后才成功为了节省每个setOnCheckedChangeListener
都要被写一遍,可以采用优化方法(但是我第一次写的时候没有记住): 就是使用接口CheckBox.OnCheckedChangeListener
课件内容如下,整体思路类似,但是只需要实现一次方法即可
The root layout is LinearLayout.
1 TextView shows your name and student number
3 RadioButtons in a row enclosed with RadioGroup
1 TextView shows the selected information of the RadioButtons when the checked state changes.
本题使用的是RadioButton这个组件
第一个考点是三个RadioButton在RadioGroup中的布局,需要为RadioGroup添加水平的属性,以及三个RadioButton的layout_weight
第二个考点.也是我看了提示的考点在java编程中,我忘记了如何获取RadioButton,只需要findViewById即可,checkedId在方法中作为参数已经传入
因为RadioGroup没有多选,所以textview只显示一个的值,直接设置text就好了
Make an app with 3 components. The root layout is LinearLayout. The 1st one is a TextViewshows your name and ID. The 2nd one is an EditText with hint message “Please input your
name”. The 3rd one is a Button. The 4th one is a TextView. When the Button clicks, the TextViewshows the content of the EditText.
耗时: 4:16.823
Make an app with 3 components. The root layout is LinearLayout. The 1st one is a TextView shows your name and ID. The 2nd one is a horizontal LinearLayout with 3 equal width Buttons. Click red Button, the TextView changes the text color to red. Click blue Button, the TextView changes the text color to blue. Click other Button, the TextView changes the text color to a customized color defined in res/values/colors.xml.
本题有1个需要注意的点
1、编写一个程序,在一个垂直布局LinearLayout里有4个水平布局的LinearLayout和3个TextView。
第一个水平布局的LinearLayout里面有1个TextView部件和EditText部件,其中TextView和EditText按1:3分布,TextView文字右对齐;
第二个水平布局的LinearLayout里面依次放有1个Button和1个TextView部件,Button点击后能把第一个水平布局里的EditText的内容更新到Button右边的TextView部件上;
第三个水平布局的LinearLayout里有一组RadioButton(三个组件所占空间平均分配,LinearLayout可不需要);
第四个水平布局的LinearLayout里有三个Checkbox(三个组件所占空间平均分配);
第五个部件为TextView,字体红色,显示RadioButton选中项(单选);
第六个部件为TextView,字体蓝色,显示CheckBox选中项(多选); 第七个部件为TextView,显示你的学号和姓名。
耗时:29:11.107
耗时: 11:08.600
本题我忘了如何获取到 res文件中自己配置的String array了
对我来说容易忘记的是后面的R.array
String[] cities = getResources().getStringArray(R.array.cities);
这里回顾一下之前那道获取color的题目 getResources().getColor(R.color.others);
如果实在忘记了R.array.cities
或者如何获取
可以直接手动写String数组,最后的效果是一样的,写在res里面可能为了便于修改维护等操作吧
String[] cities = new String[]{
"Ningbo","Beijing","Shanghai"};
另一个注意点就是ArrayAdapter了,通常通过Listview或者Spinneer来使用
ArrayAdapter(Context context, int resource, List
第一个参数是 Activity.this
第二个参数是 布局的资源ID 包含textview 最普遍的是(android.layout.simple_list_item_1
)
第三个参数是 一个数组, 里面可以放不同的类型 这里的就是String 数组
可以理解成 第三个参数里面的每个数据都会被放到一个Textview中
在他的方法中,我们可以直接使用position来感知第几个选项被点击了,结合传入的数组就知道了点击的数据是什么
之前提到了getResources().getStringArray(R.array.xxx)
可以获取资源文件中自定义的StringArray
,而这里我们定义的是array
,并且里面存放的是int
类型的Color
<array name="color_array">
<item>#f00item>
<item>#0f0item>
<item>#00fitem>
array>
所以获取方式需要修改为
final TypedArray color_array = getres.obtainTypedArray(R.array.color_array);
其在Spinner中的获取方式如下
color_array.getColor(position, Color.BLACK)
其中第二个参数是获取失败的替换方案,不一定要Black
第一种方式就是我们经常使用的
第二种方式较为方便,当资源文件不变时,可以使用如下方法创建
sp.setAdapter(ArrayAdapter.createFromResource(this,R.array.color_array,android.R.layout.simple_list_item_1));
两种方式对比
# 第一种
String[] color_name = getres.getStringArray(R.array.color_list);
sp.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, color_name));
# 第二种
sp.setAdapter(ArrayAdapter.createFromResource(this,R.array.color_name,android.R.layout.simple_list_item_1));
R,drawble.xxx
获取,最后通过imgView去设置图片scaleType
设置图片铺满规定的大小本题我第一遍很惭愧的没有做出来,问题出在SimpleAdapter的创建上,其中的一个参数应该是java.util.List extends java.util.Map
也就是说是个List 然后里面放一个Map类型的 在这里就可以是ArrayList
另一个问题出通过ListView来获取 Phonenumber,本质的原因也是对SimpleAdapter参数的不熟悉
需要如下几个参数:
context
: 显然是this
或者Activity.this
java.util.List extends java.util.Map> data
这个要注意是List
这里Map类型的第一个参数的String是确定的,他相当于python字典中key的作用,通过键来获取值,这里的值可以是String类型(姓名,电话号,也可以是int类型(图片的资源id)resource
这个遇到过很多次了 之前用的都是android.R.layout.simplexxx
,现在可以用自己定义的R.layout.xxx
String[]
这个参数表示要显示在界面的Key值,
List
类型中,我们可能放了很多字段,如电话号码,姓名,邮箱,地址,身份证号等等等等,但是在界面中我们要显示的可能只有其中的几个字段,如姓名,电话号. 所以这里的String中只要放那些你需要显示的Key值就好了int[]
注意这里的int[] 里面存放的是一堆R.id.xxx
长度必须和前面的那个参数String[]
等长,他的目的是把需要显示的Key值所对应的Value显示在界面上,所以前面的一个Key值对应这里的一个R.id
,并且位置要想对应,不然会出错. 比如第一个Key 是 PHONE_IMG
,后面的第一个id就得是R.id.img
SimpleAdapter的数据是由ArrayList和HashMap数据构造的,HashMap的键字符串可以由公共静态 final字段变量定义(先定义好 KEY
如 private String PHONE_NUMBER="PHONE_NUMBER";
这样的可读性更高,而且代码更加简洁
ArrayList
的创建与使用方式Java学的不太好 所以记一下
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
String[] names = new String[]{
"华晨宇", "薛之谦", "迪丽热巴"};
String[] numbers = new String[]{
"123456", "666666", "99999"};
for (int i = 0; i < 3; i++) {
HashMap<String, Object> map = new HashMap<>();
map.put(Phone_img, picid[i]);
map.put(Phone_name, names[i]);
map.put(Phone_number, numbers[i]);
list.add(map);
}
本质上没什么难度,理解了前两点就没问题了
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
HashMap<String, Object> map = list.get(position);
Toast.makeText(task2_5.this, map.get(Phone_number) + "has been called", Toast.LENGTH_SHORT).show();
}
});
通过positon获取到list中相应的位置数据,这里获取到的数据类型是HashMap
,所以通过HashMap.get(key_name)
就可以获取到想要的value了
跟2-5不一样的地方是,这道题对ListView中的对象作出了区分,点击不同的地方要得到不同的回应,并且当电话号码为空的时候,右边的图标不显示
当然最主要的就是自定义Adapter的操作了
自定义ArrayAdapter在很多情况下使用,一般流程如下
ArrayAdapter>
的类型row_view
extends ArrayAdapter
context
, list
(尤其重要)这里我写错了继承的对象,以及构造函数的参数
View是否可见由属性android:visibility="?"
来决定,共有三种情况
而在java代码中则可以使用形如 View.setVisibility(View.GONE);
的样子来设置
在构造函数里面有一句话是
super(context,android.R.layout.simple_list_item_1,list);
这里的layout可以随便写,因为在GetView方法中我们会设置自定义的layout
为了使得 我们自定义的layout中的UI和list中的相对应起来,
所以需要先将它转换为View 对象
转换的语句如下
设置Layout的语句很容易记错
v = LayoutInflater.from(context).inflate(R.layout.t26_row_view,null,false);
在GetView方法中通过id获取对象 需要使用v.findViewById
而在方法的最后不要忘记 return v
Write an app like GridView-task1 with 2 Textviews , and 1 GridView. The first TextView shows your name and student number. The second TextView shows the clicked item of the GridView. The GridView shows 99 string items in 3 columns. The 99 strings are generated and stored in ArrayList.
耗时: 7 : 54 : 31
context
代表上下文对象resource
代表布局的设置 可以选用默认的 也可以用自定义的List
第三个参数通常用List 来表示,List的类型要与ArrayAdapter的类型相对应, 本题用的是String类型, 因为每个格子只显示一个String 所以不用改写.stretchMode
这个属性不要忘记
更详细的各个属性会写在另一篇专门介绍GridView的文章中
本题没什么注意点 ,理解了之前的改写ArrayAdapter和GridView的基本操作即可,如果不熟练可以再去练练前面的题目
本题是简单的menu使用,仅仅使用到了menu的创建与基本应用
OptionsMenuMenu的注册 这里要与另一个Menu区分开来 ContextMenu
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.t31_menu, menu);
return super.onCreateOptionsMenu(menu);
}
item.getItemId()
来获取被选中的Itempublic boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.t31_showName:
tv.setText("TTY");
break;
case R.id.t31_showid:
tv.setText("My ID");
break;
case R.id.t31_reset:
tv.setText("");
break;
}
return super.onOptionsItemSelected(item);
}
本题是基本上下文菜单的使用与注册,有几个点还是比较容易犯错的, 和上一题的OptionMenu类似,上下文菜单的注册方法和事件监听也是通过两个方法实现的
不同的是 OptionMenu
是针对某个组件来说的,比如ListView
,GradView
,所以在使用的有2个点需要去注意
三个步骤
思路: 因为ContextMenu在注册的时候已经绑定到了组件上,如本题就绑定在了ListView上,那么我们需要获取到被点击的位置,就需要稍微花一点心思了,不能跟之前一样简简单单的用menu.position
首先onContextItemSelected
方法可以让我们获取到被点击的Item,它有如下两个功能
ContextMenu.ContextMenuInfo menuInfo = item.getMenuInfo();
AdapterView.AdapterContextMenuInfo menuInfo1 = (AdapterView.AdapterContextMenuInfo) menuInfo;
int pos = menuInfo1.position;
1.设置断点
2.Debug
可以看到,这个对象具有positon属性
接下来就简单了,补全代码获取position即可
ContextMenu.ContextMenuInfo menuInfo = item.getMenuInfo();
AdapterView.AdapterContextMenuInfo menuInfo1 = (AdapterView.AdapterContextMenuInfo) menuInfo;
int pos = menuInfo1.position;
耗时: 3:37.90
这道题很基础,没什么难度,会创建AlertDialog就行了
主要通过AlertDialog.Builder
来创建bl对象,通过bl来设置AlertDialog的各个属性
AlertDialog.Builder bl = new AlertDialog.Builder(this);
bl.setTitle("Dialog Title").setMessage("Review:My name and ID");
bl.setNegativeButton("CANCEL",null).
setPositiveButton("OK",null).show();
这里如果想设置PositiveButton
的具体功能,就把上面代码中的null改成Listen监听器即可
AlertDialog.Builder bl = new AlertDialog.Builder(this);
bl.setTitle("Dialog Title").setMessage("Review:My name and ID");
bl.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(Review33.this, "BEING CLICKED", Toast.LENGTH_SHORT).show();
}
}).setPositiveButton("OK",null).show();
比起之前AlertDialog的创建,这里就多了一步
AlertDialog.Builder bl = new AlertDialog.Builder(this);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_view_33, null, false);
// TODO
bl.setView(view);
唯一需要注意的地方是 在TODO的地方,获取alertDialog中的UI组件必须使用view.findViewById()
,不然会找不到
耗时: 7:10.56
本题可以选择使用自定义layout,在里面创建Checkbox
的方法,也可以使用AlertDialog
自带的多选框
两种形式均可实现
OnMultiChoiceClickListener
共有三个参数
booleans[which] = isChecked;
bl.setMultiChoiceItems(data, booleans, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
booleans[which] = isChecked;
}
});
耗时: 13分钟
耗时: 13:16.474
见下面的文章
安卓编程 多线程与Handler消息传递(附案例 计时器)
第一次做的时候忘记初始化AtomicBoolean
对象
第二次做的时候忘记初始化Float
对象
看报错信息后,解决问题
耗时: 40:33.539
耗时: 35:19.21
耗时: 22:13.70 (这种题目差不多要20分钟吧)
这个实验的耗时相对较长,并且在编程的过程中碰到了许多小问题
本题设计到了数据库的相关知识,如果想要盲敲的话,在理解SQLite数据库使用的基础上,还需要对代码的整体框架都有着一定的思路
本题的思路相对简单, 两个按钮实现数据的插入与重置,我的整体编程思路如下
PhoneDatabase
类中, 在里面实现 insert
,reset
,selectAll
的操作PhoneDatabase
的类中首先需要定义内部类继承SQLiteOpenHelper
并实现其中的Oncreate
与Upgrade方法
main
为主显示界面,一个row_view
为SimpleCursorAdapter
的显示样式adapter.getCursor().requery();
第二遍刷题的时候我没想起来这个,就重新设置了一个Cursor也可以实现
Cursor c1 = phoneDataBase.findAll();
adapter.swapCursor(c1);
这里要注意创建SQLiteOpenHelper
的时候version
不能等于0,否则要报错,所以在初始化的时候另version
为1
private static String Database_Name = "demo";
private static String Table_Name = "tty";
public static String KEY_NAME = "name";
public static String KEY_PHONE = "phone";
public long insert(String name, String phone)
public Cursor selectAll()
%04d
代表四位数字不足的用0来补
new Random().nextInt(10000)
生成一个10000内的数字
String phone = String.format("%04d", new Random().nextInt(10000));
data/data/项目名/database/下的db文件
右键保存
然后用工具来查看
第三遍练习的时候,我在第二遍的基础上删除代码重新测试时间,在这个过程中,因为开启的虚拟机是同一个,所以原先的数据库是依旧存在的,如果列名不一致的话会引发错误,最简单的办法就是先卸载APP再运行程序,或者在onCreate之前先执行 如果存在就删除表的操作;
Make an app like sqlite-task2.
There is a SearchView in the action bar. Users can fuzzy query the database, and the ListView shows the items match the query by name or phone number.
When the query text is empty, the ListView shows all the items of the database.
When the query text is not empty, the ListView shows all the items which fuzzy match the query text by the name or phone field of the database.
耗时: 5-1基础上7分钟
本题在5-1的基础上增加了一个模糊查询的方法
多了个OptionMenu的SearchView组件使用
基本上会5-1的话这题就一个点比较容易出错,如下注意点1
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.opt_search, menu);
MenuItem item = menu.findItem(R.id.menu_search);
SearchView searchView = (SearchView) item.getActionView();
}
getMenuInflater().inflate(R.menu.opt_search, menu);
这句话要记住inflate
就可以了
MenuItem item = menu.findItem(R.id.menu_search);
其实跟findViewbyId类似
SearchView
的Id找到SearchView
所在的Item
(findItem)item.getActionView
找到对应的searchView
(item.getActionView)swap
很明显是更换用的
adapter.swapCursor(cursor);
Writing an App about contact with sqlite database,the root layout is a vertical LinearLayout with 2 components. The App’s name should contain your name message (initials of your name).
–The 1st component is a TextView, which shows your name and student number.
–The 2nd component is a ListView shows the queried cursor.
There are 3 Options MenuItems: search, new and reset. The items for search and new are shown in the action bar with icons. When users click the SearchView, the ListView shows the fuzzy query result.
The ListView registers a ContextMenu with 3 MenuItems: modify, delete and new. For modifying and new data, an AlertDialog pops up and shows the data for editing.
The ListView updates everytime for the CRUD opertations.
耗时: 在2的基础+49:22.75F分钟
除了与adapter绑定的游标外,其他的游标用完最好关闭,否则比较占内存
LayoutInflater
方法可以将资源文件妆花为一个View对象
本道题第一遍花的时间有点久
在创建CursorWrapper对象的时候可以先把游标移动到first的位置(因为这个功能只有在修改的时候要用)
先定位,后取数据(默认的位置在-1)
moveToFirst()
moveToNext()
moveToPosition(int position)
getColumnIndex(String columnName)
getString(int columnIndex)
通用的步骤如下
已知要取的列名为KEY_NAME
带着数据的游标为 c
c.getString(c.getColumnIndex(KEY_NAME));
它可以当做cursor来用,优点是可以实现一些自定义的功能,使得代码更加高效,否则就要用cursor一句一句的去写
在本题中,它的作用是实现了修改数据的时候显示指定ID的值,并显示在Dialog上
以及点击发送短信的时候显示phone字段
如果为了做出题目忘记了CursorWrapper怎么用可以不写
对于弹出对话框,不知道要执行的是修改还是插入,所以可以使用一个监听器接口,把editText的内容回传到主线程中,再做相应的操作
其流程如下
自定义一个Show方法来展示数据, 传入name,和 phone
将name 和 phone设置到editText上
如果是修改,就传入数据
如果是新增,就传入空数据