1.按钮四种点击事件写法
[1]通过内部类来实现按钮点击事件
[2]通过匿名内部类去实现
btn_test1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"我被点击了",Toast.LENGTH_LONG).show();
}
});
[3]当页面上有多个按钮 让当前类实现OnClickListener.通过switch语句 通过id 来判断具体点击的是哪个按钮
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.找的按钮
Button btn_test1 = (Button) findViewById(R.id.button1);
Button btn_test2 = (Button) findViewById(R.id.button2);
Button btn_test3 = (Button) findViewById(R.id.button3);
Button btn_test4 = (Button) findViewById(R.id.button4);
/* //2.通过查看 api文档得知 可以通过匿名内部类去实现
btn_test1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"我被点击了",Toast.LENGTH_LONG).show();
}
});*/
//3 当页面上有多个按钮需要点击的时候 可以这样写
btn_test1.setOnClickListener(this);
btn_test2.setOnClickListener(this);
btn_test3.setOnClickListener(this);
btn_test4.setOnClickListener(this);
}
@Override
public void onClick(View v) {
//4.由于每个按钮的id 不一样 所以可以通过id来判断用户到底点击的是哪个按钮
switch (v.getId()){
case R.id.button1:
Toast.makeText(MainActivity.this,"我被点击了111",Toast.LENGTH_LONG).show();
break;
case R.id.button2:
Toast.makeText(MainActivity.this,"我被点击了222",Toast.LENGTH_LONG).show();
break;
case R.id.button3:
Toast.makeText(MainActivity.this,"我被点击了333",Toast.LENGTH_LONG).show();
break;
case R.id.button4:
Toast.makeText(MainActivity.this,"我被点击了444",Toast.LENGTH_LONG).show();
break;
}
}
}
[4]按钮第四种点击事件写法
[4.1]在按钮上声明一个onClick属性
<Button
android:text="test5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="16dp"
android:onClick="click"
android:id="@+id/button5" />
[4.2]在mainActivity写一个方法 要求方法名和属性名一样 并且接收一个参数 参数类型View.
public void click(View v){
Toast.makeText(MainActivity.this,"我被点击了555",Toast.LENGTH_LONG).show();
}
按钮继承的是view类,看view的原码,Ctrl+f
搜 onclick,原理就是我们前面讲的反射,通过属性名,反射“click”方法
反射用的是
(不知道为什么我的看不到原码)
所以click方法必须是public的。
实际开发中:使用匿名内部类或者第四种写法
2.android中常见布局
[1]线性布局 水平 垂直.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"//设置朝向,这个是垂直,另一个是水平
android:layout_height="match_parent">
<!--@符合就代表R文件-->
<TextView
android:id="@+id/tv_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入手机号:"
android:textSize="25sp"
/>
<EditText
android:id="@+id/et_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入手机号"//输入前的输入提示
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="拨打此号码"
/>
</LinearLayout>
[2]相对布局 里面的控件默认都从左上角开始排列
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--快速格式化代码 ctrl + alt + l-->
<!--@符合就代表R文件-->
<TextView
android:id="@+id/tv_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入手机号:"
android:textSize="25sp" />
<EditText
android:id="@+id/et_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv_number"
android:hint="请输入手机号"1
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/et_number"//_above代表处在谁上面。_torightof右面;_toleftof左面
android:text="拨打此号码"
/>
</RelativeLayout>
[3]帧布局 分层展示控件,特点就是叠在一起(两个控件都是
match_parent
的情况下
)不会出现覆盖,而是分层展示
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--@符合就代表R文件-->
<TextView
android:id="@+id/tv_number"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="这是视频播放的内容:"
android:textSize="25sp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="拨打"
android:layout_gravity="center"//相对于父亲居中;
center_ vertical 水平居中//还有一个 android : gravity = "center" 这个相对于控件本身居中/>
</FrameLayout>
[4]表格布局 表格由行和列构成
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--一个tablerow就代表一行 具体的控件表示列-->
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1111" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2222" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1111" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2222" />
</TableRow>
</TableLayout>
[5]绝对布局 已经过时 我们开发中很少用
AbsoluteLayout 设置宽高layout_height/width,位置layou_x/y = "12dp"
[6]总结:实际开发中我们使用线性布局和相对布局组合.
3.android中单位
px
给控件或者布局设置一个具体的宽和高.(这个不建议使用,因为会固定大小)
http://blog.csdn.net/jiangwei0910410003/article/details/40509571
px :是屏幕的像素点
dp :一个基于density的抽象单位,如果一个160dpi的屏幕,1dp=1px
dip :等同于dp
sp :同dp相似,但还会根据用户的字体大小偏好来缩放(建议使用sp作为文本的单位,其它用dip)
dp :一个基于density的抽象单位,如果一个160dpi的屏幕,1dp=1px
dip :等同于dp
sp :同dp相似,但还会根据用户的字体大小偏好来缩放(建议使用sp作为文本的单位,其它用dip)
4.android中单元测试
1.根据是否知道源代码 黑盒(不知道源码) 白盒(需要知道源代码)
2.根据测试粒度 方法 单元(和方法测试一个意思) 系统(ee比较多) 集成 (安卓,比如美团的客户端和服务端要集成到一起,测试一下)
3.根据测试的暴力程度 压力(12306,就是同时访问人数) 冒烟(一直把设备测到冒烟为止) 谷歌提供了一个工具(monkey) cmd--adb shell--monkey--monkey 1000
然后直接点旁边的
public class ExampleUnitTest {
@Test
public void testAdd(){
Calc calc = new Calc();
int add = calc.add(3, 5);
//判断一下结果是真的还是假的 断言: 参数1:期望值 参数2:实际值
assertEquals(8,add);
}
}
5.Log类的使用
System.out.println("aab");
//android开发中 谷歌单独提供了打印日志的类 Log 参数1:对log信息的标示 参2:就代表具体打印的日志信息
Log.e("MainActivity","e级别");
Log.w("MainActivity","w级别");
Log.d("MainActivity","d级别");
Log.i("MainActivity","i级别");
Log.v("MainActivity","v级别");
1.android.util.Log常用的方法有以下5个:Log.v() Log.d() Log.i() Log.w() 以及 Log.e() 。根据首字母对应VERBOSE,DEBUG,INFO, WARN,ERROR。
2、Log.v 的调试颜色为黑色的,任何消息都会输出,这里的v代表
verbose啰嗦的意思,平时使用就是Log.v(“”,”“);
3、Log.d的输出颜色是蓝色的,仅输出
debug调试的意思,但他会输出上层的信息,过滤起来可以通过DDMS的Logcat标签来选择.
4、Log.i的输出为绿色,一般提示性的
消息information,它不会输出Log.v和Log.d的信息,但会显示i、w和e的信息
5、Log.w的意思为橙色,可以看作为
warning警告,一般需要我们注意优化Android代码,同时选择它后还会输出Log.e的信息。
6、Log.e为红色,可以想到
error错误,这里仅显示红色的错误信息,这些错误就需要我们认真的分析,查看栈的信息了。
7.注意:不同的打印方法在使用时都是某个方法带上(String tag, String msg)参数,tag表示的是打印信息的标签,msg表示的是需要打印的信息,例如。
6.登录案例
代码实现[1]:画ui
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.itheima.login.MainActivity">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" 后面加的:
android : inputType = "textPassword"// 代表输入格式为文字,不可见android:hint="请输入用户名"
/>
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_marginTop="20dp"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/cb_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住用户名密码"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录"
android:layout_alignParentRight="true"//表示靠近父亲的右边
android:onClick="click"
/>
</RelativeLayout>
</LinearLayout>
[2]根据ui写对应的业务逻辑
[2.1]登录流程如下:
[2.2]把用户名和密码保存起来 由于保存数据和读取数据业务逻辑是独立的所以单独写到一个工具类里
public class UserUtils {
//用来存储用户密码业务方法 ctrl + alt + t 抓异常
public static boolean save(String name, String pwd) {
try {
//1.为了存储方便 拼接字符串
String data = name + "##"+pwd;
//2.把data存到手机里(不能存到 C ,D盘) ---->手机里有内部存储目录() 和 外部存储目录
File file = new File("/data/data/com.itheima.login/info.txt");
//3.创建一个文件输入流
FileOutputStream fos = new FileOutputStream(file);
//4.把data写到文件
fos.write(data.getBytes());
//5.关流
fos.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//读取info.txt文件里面的内容
public static Map<String,String> readInfo(){
try {
//1.创建一个map对象用来存储 我们读取出来的数据
Map<String,String> maps = new HashMap<>();
//2.去info.txt文件里面读
File file = new File("/data/data/com.itheima.login/info.txt");
//3.创建FileinputStream
FileInputStream fis = new FileInputStream(file);
//4.使用一个转换流 可以快速读取一行数据
BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
//5.读一行 把结果数据读取出来
String result = bufr.readLine(); // aa##123
//6.切割字符串 根据##
String[] split = result.split("##");
//7.获取用户名 aa
String name = split[0];
//8.获取密码
String pwd = split[1];
//9.把name 和 pwd存到集合里
maps.put("name",name);
maps.put("pwd",pwd);
return maps;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
[2.3]当保存数据就调用save方法 当读取数据就调用readinfo方法
7.Context类(上下文)
灯坏了 ----->工具箱找板子 ---修灯
宝马x6 ----->
工具箱找对应工具
上下文就是谷歌给我们提供的一个工具类。上下文中的方法很多,都可以直接调用。
8.把数据存储到sd卡
[8.1]会获取sd卡路径
String sdPath = Environment.getExternalStorageDirectory().getPath();
[8.2]判断sd卡状态是否可用
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){ }
[8.3]如何判断sd卡空间是否够用
//1.获取sd卡空间
File file = Environment.getExternalStorageDirectory();
//2.在file类中提供了2个方法 可以获取总空间 和 可用空间 谷歌已经帮助我们封装了
long totalSpace = file.getTotalSpace();
long usableSpace = file.getUsableSpace();
//3.所以需要把值转换为对应的单位 参数1:上下文this, //TODO 明天讲
String totalSpaceSize = Formatter.formatFileSize(this, totalSpace);
String usableSpaceSize = Formatter.formatFileSize(this, usableSpace);
System.out.println("total:"+totalSpaceSize);
System.out.println("usable:"+usableSpaceSize);
建议使用 adb 指令
9.文件权限
10.SharedPreferences偏爱 喜爱
//3.说明用户名密码不为空 使用sp来存数据 获取sp的实例
SharedPreferences sp = getSharedPreferences("config", 0); //:使用sp 系统会生成一个xml格式的文件
//3.1 获取sp的编辑器
SharedPreferences.Editor edit = sp.edit();
//3.2 存数据 用户名 和密码
edit.putString("name",name);
edit.putString("pwd",pwd);
//3.3 调用commit方法提交数据
edit.commit();
11.今天总结
1.按钮四种点击事件写法 ☆
☆
☆
2.android五大布局
☆
☆
☆
3.android 单位 dp sp
☆
☆
☆
4.android单元测试
☆
☆
☆ asserteaquals 断言
5.monkey 2000
☆
6.Log类
☆
☆
☆
7.登录案例
☆
☆
☆
8.Context
☆
☆
☆
//类名.this this区别
9.把数据存储到sd卡
☆
☆
☆
10.文件权限
☆
11.sp存储数据
☆
☆
☆
adb指令
☆
☆
☆
1.拨打电话
1.画xml
2.新建类,继承
AppCompatActivity
,覆盖方法,获取布局路径
public class MainActivity extends AppCompatActivity {
private List<Sms> lists;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);//这里是获取
3.查看api,找到按钮的用法。获取方法
Button btn_test1 = (Button) findViewById(R.id.button2);
4.监听按钮
btn_test1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"我被点击了",Toast.LENGTH_LONG).show();
}
});
5.再监听里面写打电话的逻辑,用Intent类,是studio里面定义好工具。
获取号码:
String
number
=
et_number
.
getText
().
toString
().
trim
();
新建Intent类:
Intent
intent
=
new
Intent
();
调用intent打电话动作:
intent
.
setAction
(
Intent
.
ACTION_CALL
);
传入数据:
intent
.
setData
(
Uri
.
parse
(
"tel:"
+
number
));
开启动作:
startActivity
(
intent
);
6.开启权限:谷歌工程师的代理权限,谁写谁负责,反正意思就是和谷歌无关。(下面代码加到main文件夹里面的AndroidManifest.
xml的声明下面,大概第三行)
<
uses
-
permission android
:
name
=
"android.permission.CALL_PHONE"
></
uses
-
permission
>
2.新建模拟器要开这个,开了以后再重新启动模拟器
2.登录案例(步骤看老师笔记,下面是详细代码)
1.先写xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.itheima.login.MainActivity">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名" />
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="请输入密码" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<CheckBox
android:id="@+id/cb_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住用户名密码" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:onClick="click"
android:text="登录" />
</RelativeLayout>
</LinearLayout>
2,主类
package com.itheima.login;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Map;
/**
* Author: 邱珑
* Version: 1.0
* Date: 2017/8/21
* Modify:
* Description: //TODO
* Copyright notice:
*/
public class Test extends AppCompatActivity {
private TextView tx1;
private TextView tx2;
private CheckBox cb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
tx1 = (TextView) findViewById(R.id.textView1);
tx2 = (TextView) findViewById(R.id.textView2);
cb = (CheckBox) findViewById(R.id.checkBox);
Map<String,String> map = UserUtils.read();
if(map.equals(null)){
}else{
tx1.setText(map.get("name"));
tx2.setText(map.get("pwd"));
}
}
public void click(View view){
String name = tx1.getText().toString().trim();
String pwd = tx2.getText().toString().trim();
if(TextUtils.isEmpty(name)||TextUtils.isEmpty(pwd)){
Toast.makeText(this,"用户名或密码不能为空",Toast.LENGTH_LONG).show();
}
else if(cb.isChecked()){
boolean a = UserUtils.save(this,name,pwd);
if(a){
Toast.makeText(this,"成功",Toast.LENGTH_LONG).show();
}else
Toast.makeText(this,"失败",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this,"没有勾选保存信息",Toast.LENGTH_LONG).show();
}
}
}
3.UserUtils类
package com.itheima.login;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
/**
* Created by jinxi on 2017/8/20.
*/
public class UserUtils {
public static boolean save(String name, String pwd) {
String num = name+"##"+pwd;
File f = new File("data/data/com.itheima.login/info.txt");
try {
FileOutputStream fos = new FileOutputStream(f);
fos.write(num.getBytes());
fos.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static Map<String,String> read(){
Map<String,String> map = new HashMap();
File f = new File("data/data/com.itheima.login/info.txt");
try {
FileInputStream fis = new FileInputStream(f);
BufferedReader br = new BufferedReader(new FileReader(f));
String a =br.readLine();
String[] as =a.split("##");
map.put("name",as[0]);
map.put("pwd",as[1]);
return map;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
4.优化代码:使用context代替写死的地址输入
这里需要在把
UserUtils类中save方法和read方法添加一个参数
save
(
String
name
,
String
pwd
)----->
save
(
Context context,
String
name
,
String
pwd
)
String path = context.getFilesDir().getPath();
File f = new File(path,"info21.txt");//后面是给文件命名
//File f = new File("data/data/com.itheima.login/info.txt");
再次改进,直接用context里面的方法,后面也要改,这里省略了
// String savePath = context.getFilesDir().getPath(); // data/data/当前应用包名/files/
// File file = new File(savePath,"info2.txt");
// FileOutputStream fos = new FileOutputStream()
//3.创建一个文件输入流 mode参数: 0:代表私有的模式
FileOutputStream fos = context.openFileOutput("info3.txt", 0); //info3.txt // data/data/当前应用包名/files/
先改老师笔记,有多余时间,在通过修改的笔记写自己的理解
1.按钮四种点击事件写法 ☆
☆
☆
2.android五大布局
☆
☆
☆
3.android 单位 dp sp
☆
☆
☆
4.android单元测试
☆
☆
☆ asserteaquals 断言
5.monkey 2000
☆
6.Log类
☆
☆
☆
7.登录案例
☆
☆
☆
8.Context
☆
☆
☆
//类名.this this区别
9.把数据存储到sd卡
☆
☆
☆
10.文件权限
☆
11.sp存储数据
☆
☆
☆
adb指令
☆
☆
☆