Android移动应用开发

  • 1、认识Android
  • 2、Android界面开发方法
    • 2.1 布局控件
    • 2.2 Android常用公有属性
    • 2.3 线性布局 LinearLayout
    • 2.4 values下xml 技巧
    • 2.5 button的使用
    • 2.6 shape图形 selector
    • 2.7 相对布局ReLativeLayout的使用
    • 2.8 Spinner控件的使用
    • 2.9 Dialog对话框对的使用
  • 3、界面跳转的实现
    • 3.1 认识Intent
    • 3.2 Activity间的数据传递
    • 3.3 Activity生命周期
  • 4、用户信息的存储
    • 4.1 简单存储SharedPreferences
    • 4.2 文件存储
  • 5、ListView的应用
    • 5.1 使用Adapter设置数据及布局
    • 5.2 简单适配器SimpleAdapter
    • 5.3 自定义适配器
    • 5.4 ViewHolder用法
  • 6、单选及复选按钮
    • 6.1 复选按钮(CheckBox)
    • 6.2 单选按钮(RadioButton)
  • 7、Fragment碎片
    • 7.1 认识Fragment
    • 7.2 添加Fragment
    • 7.3 Fragment的生命周期
  • 8、SQLite数据库
    • 8.1 认识SQLite数据库
    • 8.2 SQLite数据库的创建
    • 8.3 SQLite数据库的升级
    • 8.4 SQLite数据库的查看
    • 8.5 SQLite数据库的基本操作

1、认识Android

1、Android的体系架构
应用程序、应用程序框架、核心类库、Linux内核
2、Dalvik虚拟机

3、ART虚拟机

2、Android界面开发方法

2.1 布局控件

1、Android界面分为布局控件
2、布局类LinearLayout 继承自 ViewGroup
控件类TextView 继承自 View(所有UI类的父类)

3、小结

带+在r文件中自动生成一个常量代替该文件
android:id=“@+id/button”

2.2 Android常用公有属性

1、layout_width、layout_height 设置控件宽高
wrap_content 包裹内部控件
match_parent 填充父容器

2、layout_margin 控件的外边距

3、padding 控件的内边距

4、设置控件相对位置
layout_gravity 控件相对于父控件的位置
gravity 控件内容相对于控件的位置
靠左、靠右、顶部、底部:left、right、top、bottom
居中:center
水平居中:center_horizontal
垂直居中:center_vertical

2.3 线性布局 LinearLayout

1、排列规则:水平排列垂直排列
注意:默认是水平,控件不会自动换行,超出布局的不显示
2、特有属性 orientation 设置方向
水平:horizontal 从左到右
垂直:vertical 从上到下

3、layout_weight




4、background和backgroundIint
background:除了纯色背景还可以加图片
backgroundIint:适用于api level 21 更高的版本
5、setTextColor修改颜色的三种方式
(Color.RED)
(Color.rgb(0,0,255))
(Color.parseColor(“#66CCFF”))

2.4 values下xml 技巧

1、colors.xml 定义颜色

<resources><color name="color">#3F51B5</color>
</resources>android:textColor="@color/color"

2、string.xml 定义字符串

<resources><string name="hello">hello</string>
</resources>android:text="@string/hello"

2.5 button的使用

1、ImageButton

<ImageButtonandroid:id="@+id/button16"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/selector_button"android:scaleType="fitXY"android:src="@mipmap/sqrt" />

src:前景
background:背景
fitXY:图片适应控件大小

2、单个Button的事件处理

button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {textView.setTextColor(Color.parseColor("red"));}
});

3、多个Button的事件处理
总体思路:使用switch方法

在Activity中实现事件监听接口

public class MainActivity extends AppCompatActivity implements View.OnClickListener{//此处省略部分代码@Overridepublic void onClick(View view) {switch (view.getId()){case R.id.button:textView.setTextColor(Color.parseColor("red"));break;case R.id.button2:textView.setTextColor(Color.YELLOW);break;case R.id.button3:textView.setTextColor(Color.GREEN);break;}}
}

也可在Activity构造方法后,在xml布局中调用onClick

    <Buttonandroid:id="@+id/button"android:text="红色"android:backgroundTint="@color/red"style="@style/buttonstyle" android:onClick="doLogin"/>

2.6 shape图形 selector

1、利用shape属性构建一个圆形

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<!--    大小--><size android:height="180dp" android:width="400dp"/>
<!--    填充颜色--><solid android:color="@color/white"/>
<!--    描边-->
<stroke android:color="@color/black" android:width="1dp" android:dashWidth="3dp" android:dashGap="1dp"/>
<!--    圆角半径--><corners android:radius="10dp"/>
</shape>

2、selector 点击图片后显现另一个图片

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--    不设置状态的这一行,一定要写在最后面,否则不起作用--><item android:state_pressed="true" android:drawable="@drawable/button_pressed_orig"/><item android:drawable="@drawable/button_normal_orig"/>
</selector>

2.7 相对布局ReLativeLayout的使用

1、兄弟控件

2、父控件

2.8 Spinner控件的使用

1、spinner列表框模式
android:spinnerMode
dialog:弹出对话框
dropdown:下拉框

android:entries 设置列表项,值为数组资源
android:popupBackground 设置下拉项的背景
2、spinner列表框实现方式一

    <Spinnerandroid:id="@+id/spanner_dropdown"android:layout_width="wrap_content"android:layout_height="wrap_content"android:entries="@array/dropdown"android:spinnerMode="dropdown"android:popupBackground="@color/teal_700"></Spinner>

values/arrs.xml

<resources><string-array name="dropdown"><item>软件二班</item><item>软件一班</item><item>软件三班</item><item>软件四班</item></string-array>
</resources>

2、spinner列表框实现方式二

    <Spinnerandroid:id="@+id/spinner_dialog"android:layout_width="wrap_content"android:layout_height="wrap_content"android:spinnerMode="dialog"></Spinner>
  //1.获取列表控件spinner=findViewById(R.id.spinner_dialog);//2.准备数据String arr[]=new String[]{"北京","上海","潍坊","西双版纳"};//3.创建adapter适配器对象上下文、列表项数据的布局数据//this 当前类对象对象,监听器类,监听器不能充当上下文ArrayAdapter arrayAdapter=new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1,arr);//4.设置adapterspinner.setAdapter(arrayAdapter);

2.9 Dialog对话框对的使用

1、简单对话框
(1)调用AlertDialog 的静态内部类 Builder创建AlertDialog. Builder对象。
(2)调用AlertDialog.Builder的 setTitle()和setIcon( )方法设置对话框的标题名称和图标。
(3)调用AlertDialog.Builder 的setMessage( )、setSingleChoiceItems()等方法设置对话框的提示信息、单选选项等显示内容。
(4)调用AlertDialog.Builder的setPositiveButton()和 setNegativeButton()方法设置对话框的“确认”和“取消”按钮。
(5)调用AlertDialog. Builder 的 create()方法创建AlertDialog 对象。
(6)调用AlertDialog 对象的show()方法显示对话框。
(7)调用AlertDialog对象的dismiss()方法取消对话框。
2、单选对话框

private void genderDialog() {String[] genders=new String[]{"男","女"};AlertDialog.Builder builder=new AlertDialog.Builder(this);builder.setTitle("选择性别");builder.setSingleChoiceItems(genders, 0, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {gender1.setText(genders[i]);dialogInterface.dismiss();}});AlertDialog dialog=builder.create();dialog.show();}

3、多选对话框

 AlertDialog.Builder b = new AlertDialog.Builder(this);final String items[]=new String[]{"音乐", "画画", "游泳", "电影", "游戏", "运动"};boolean[] checks=new boolean[]{false, false, false, false, false, false};b.setTitle("选择你喜欢的项目:");/*b.setMultiChoiceItems第一个参数为复选按钮组,第二个为是否默认选中,对应复选按钮组,true为默认选中,第三个为监听事件*/b.setMultiChoiceItems(items, checks, new DialogInterface.OnMultiChoiceClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which, boolean isChecked) {Toast.makeText(MainActivity.this, "你选择了"+items[which], Toast.LENGTH_SHORT).show();}});b.setPositiveButton("确定", null);b.show();//显示对话框

4、日期对话框

private void birthdayDialog() {Calendar c=Calendar.getInstance();int year1=c.get(Calendar.YEAR);int month1=c.get(Calendar.MONTH);int day1=c.get(Calendar.DAY_OF_MONTH);DatePickerDialog dialog=new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {@Overridepublic void onDateSet(DatePicker datePicker, int i, int i1, int i2) {birthday1.setText(i+"年"+(i1+1)+"月"+i2+"日");}},year1,month1,day1);dialog.show();}

5、自定义对话框

private void usernameDialog() {View v=View.inflate(this,R.layout.dialog_username,null);AlertDialog.Builder builder=new AlertDialog.Builder(this);builder.setTitle("修改昵称");builder.setView(v);builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {EditText ed1_up=v.findViewById(R.id.ed1);String name=ed1_up.getText().toString().trim();username1.setText(name);}});builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {}});AlertDialog dialog=builder.create();dialog.show();}

3、界面跳转的实现

3.1 认识Intent

1、显式Intent

 Intent intent=new Intent(MainActivity.this,SecondActivity.class);startActivity(intent);

2、隐式Intent

AndroidManifest.xml

        <activityandroid:name=".MainActivity"android:exported="true"><intent-filter>//过滤器<action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".SecondActivity"android:exported="false"><intent-filter><action android:name="com.example.appjump.SecondActivity"/><category android:name="android.intent.category.DEFAULT"/></intent-filter></activity>

MainActivity.java

 Intent intent=new Intent("com.example.appjump.SecondActivity");startActivity(intent);

3.2 Activity间的数据传递

1、向下一个Activity传递数据
(1)、单个存取

 Intent intent=new Intent("com.example.appjump.SecondActivity");String t=t1.getText().toString().trim();intent.putExtra("text",t);
 Intent intent=getIntent();String text=intent.getStringExtra("text");

(2)、打包存取

 Intent intent=new Intent("com.example.appjump.SecondActivity");Bundle bundle=new Bundle();bundle.putString("name",uname);bundle.putString("password",pas);intent.putExtra(bundle);
 Intent intent=getIntent();Bundle bundle=intent.getExtras();String name=bundle.getString("name");String password=bundle.getString("password");

2、返回数据给上一个Activity

 @Overridepublic void onClick(View view) {switch (view.getId()){case R.id.button1:Intent intent=new Intent("com.example.appjump.SecondActivity");String t=t1.getText().toString().trim();intent.putExtra("text",t);startActivityForResult(intent,2);break;}}
 @Overridepublic void onClick(View view) {Intent intent1=new Intent(SecondActivity.this,MainActivity.class);String t2=e1.getText().toString().trim();intent1.putExtra("text2",t2);setResult(RESULT_OK,intent1);}
 @Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);if(requestCode==2){if(resultCode==RESULT_OK){String text2=data.getStringExtra("text2");t1.setText(text2);}}}

3.3 Activity生命周期

    @Overridepublic void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {super.onCreate(savedInstanceState, persistentState);Log.e("生命周期","onCreate");}@Overrideprotected void onStart() {super.onStart();Log.e("生命周期","onStart");}@Overrideprotected void onResume() {super.onResume();Log.e("生命周期","onResume");}@Overrideprotected void onPause() {super.onPause();Log.e("生命周期","onPause");}@Overrideprotected void onStop() {super.onStop();Log.e("生命周期","onStop");}@Overrideprotected void onRestart() {super.onRestart();Log.e("生命周期","onRestart");}@Overrideprotected void onDestroy() {super.onDestroy();Log.e("生命周期","onDestroy");}@Overrideprotected void onSaveInstanceState(@NonNull Bundle outState) {super.onSaveInstanceState(outState);Log.e("生命周期","onSavaInstanceState");}

4、用户信息的存储

4.1 简单存储SharedPreferences

1、存储形式
键值对

2、存储位置
/data/data/<包名>/shared-prefs
3、存数据

 SharedPreferences spf=getSharedPreferences("data",MODE_PRIVATE);SharedPreferences.Editor editor=spf.edit();editor.putString("username","nolan");editor.putString("password","123456");editor.commit();

4、取数据

 SharedPreferences spf1=getSharedPreferences("data",MODE_PRIVATE);String name=spf1.getString("username","admin");//第二个参数为默认值

4.2 文件存储

1、内部存储
(1)存储位置
/data/data/<包名>/files
(2)存文件

 private void saveData() {//String fileName="mydb.txt"; //文件名称//String strNr="HelloWorld,我被写出来啦!";//要保存的数据String a=ed1.getText().toString();FileOutputStream fos=null;try {fos=openFileOutput(fileName,MODE_PRIVATE);fos.write(a.getBytes());//将数据写入文件中去Toast.makeText(this,"存入数据成功",Toast.LENGTH_LONG).show();} catch (Exception e) {e.printStackTrace();}finally {try {if(fos!=null) {fos.close();}}catch (Exception ex){ex.printStackTrace();}}}

(3)取文件

 private void readData() {String strNr="";FileInputStream fis=null;try {fis=openFileInput(fileName);//获取输入流对象byte[] buffer=new byte[fis.available()]; //创建数据的缓冲fis.read(buffer);strNr=new String(buffer);//将内容转换成字符串text.setText(strNr);Toast.makeText(this,"读取数据成功",Toast.LENGTH_LONG).show();}catch (Exception ex){ex.printStackTrace();} finally {try {if(fis!=null){fis.close();}}catch (Exception ex){ex.printStackTrace();}}}

2、外部存储
(1)存储位置
Environment.getExternalStorageDirectory().getPath():该方法返回外部存储根路径,返回值为"String"
/storage/emulated/0
(2)创建文件

 public static File getFile(String filePath) {//通过文件路径创建文件对象File file = new File(filePath);//判断父文件夹是否存在 如果不存在则创建文件夹if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}//判断文件是否存在 如果不存在则创建文件if (!file.exists()) {try {file.createNewFile();} catch (Exception e) {Log.e("创建失败", e.getMessage());}}return file;}

(3)申请权限
1、Androud6.0以下的版本
在AndroidManifest.xml中对所需权限进行声明
manifest节点和application节点之间

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

2、Androud6.0~10.0的版本
步骤一:在Activity的onCreate()方法中,添加动态权限申请

 if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED){Log.e("权限问题","有权限么");ActivityCompat.requestPermissions(this,new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},1);}else {saveData(filePath, a);}

步骤二:添加回调方法onRequestPermissionsResult()

 @Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if(requestCode==1){//判断请求码for(int i=0;i<permissions.length;i++){//循环判断权限授予结果if(grantResults[i]==PackageManager.PERMISSION_GRANTED){Toast.makeText(this,"权限"+permissions[i]+"申请成功",Toast.LENGTH_LONG).show();}else {Toast.makeText(this,"权限"+permissions[i]+"申请失败",Toast.LENGTH_LONG).show();}}}}

3、Androud10.0以上的版本
在AndroidManifest.xml的application节点中,加入以下属性设置

 android:requestLegacyExternalStorage="true"

(4)存文件

 private void saveData(String filePath,String content) {//调用getFile()方法创建文件并返回File file=getFile(filePath);FileWriter fw=null;BufferedWriter bw=null;try {//创建缓冲流对象实现数据的写入fw=new FileWriter(file,false);bw=new BufferedWriter(fw);bw.write(content);Toast.makeText(this,"数据存入成功",Toast.LENGTH_LONG).show();} catch (IOException e) {Log.e("写文件出错",e.getMessage());}finally {try {//先关包装流,再关节点流if(bw!=null)bw.close();if(fw!=null)fw.close();}catch (IOException e){e.printStackTrace();}}}

(5)取文件

 private String readData(String filePath) {File file=new File(filePath);String s=null;StringBuilder stringBuilder=new StringBuilder();FileReader fr=null;BufferedReader reader=null;int count=0;try{//创建缓冲流对象fr=new FileReader(file);reader=new BufferedReader(fr);//循环按行读取数据while ((s=reader.readLine())!=null){stringBuilder.append(s);}Toast.makeText(this,"数据读取成功",Toast.LENGTH_LONG).show();}catch (Exception e){Log.e("读取文件出错",e.getMessage());}finally {try{if(reader!=null)reader.close();if(fr!=null)fr.close();}catch (IOException e){e.printStackTrace();}}return stringBuilder.toString();}

5、ListView的应用

5.1 使用Adapter设置数据及布局

1、在布局文件中加入ListView控件
2、写好列表项的布局文件
3、准备将要在列表项中显示的数据,可以为数组或集合
4、创建Adapter对象,设置选中项的显示布局和数据
5、将Adapter对象设置给ListView对象

5.2 简单适配器SimpleAdapter

将数据转给布局中的控件

 //List继承自Map集合,data:List对象,List中的对象:Map集合的对象,Map对象:键:String  值:不知道是什么类型//一个Map对象代表一个列表项,有几个列表项就有几个Map//准备数据String[] names=new String[]{"太阳","水星","金星","地球","火星","木星","土星","天王星","海王星"};int[] images=new int[]{R.mipmap.ty,R.mipmap.sx,R.mipmap.jx,R.mipmap.dq,R.mipmap.hx,R.mipmap.mx,R.mipmap.tx,R.mipmap.twx,R.mipmap.hwx};//创建一个List对象ArrayList list=new ArrayList();//一个列表项的数据组成一个Map对象for(int i=0;i< names.length;i++){HashMap map=new HashMap();map.put("image",images[i]);map.put("name",names[i]);list.add(map);}//准备适配器 //第1个参数:上下文对象,第2个参数:数据集合 List集合,其中元素是Map对象,第3个参数:列表项布局//第4个参数:Map中键的数组,第5个参数:是布局中控件的id,键和id的数组要一一对应SimpleAdapter adapter=new SimpleAdapter(this,list,R.layout.item_list,new String[]{"image","name"},new int[]{R.id.iv_icon,R.id.tv_name});//列表项item点击事件处理l1.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Override//第1个参数:点击的Adapter对象,第2个参数:点击的item,第3个参数:位置 第i个item,第4个参数:item在listview第几行 一般3和4是一样的public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {Toast.makeText(ListActivity.this, "您选择的是"+names[i], Toast.LENGTH_SHORT).show();}});

5.3 自定义适配器

ArrayAdapter适用于列表项中包含一个TextView
SimpleAdapter有固定的数据组织形式
ArrayAdapterSimpleAdapter继承BaseAdapter抽象类

1、MyAdapter.java 自定义适配器将存储的数据转给控件

 public class MyAdapter extends BaseAdapter {private List<Planet> data;//数据集合private int layoutId;//列表项布局idprivate Context context;//上下文对象public MyAdapter(Context context,List<Planet> data,int layoutId){this.context=context;this.data=data;this.layoutId=layoutId;}//获取列表项个数@Overridepublic int getCount() {return data.size();}//获取i位置上的列表项对象@Overridepublic Object getItem(int i) {return data.get(i);}//获取i位置上的列表项的id,当前元素的位置@Overridepublic long getItemId(int i) {return i;}//将i位置上的数据放到列表项布局中@Overridepublic View getView(int i, View view, ViewGroup viewGroup) {//数据位置 List集合data中,取出i位置的数据Planet planet=data.get(i);String name=planet.getName();int image=planet.getImage();//通过Inflater对象的inflate方法将布局转成一个view对象,再通过view对象findViewById找控件//获取LayoutInflater实例,从一个Context中,获得一个布局管理器LayoutInflater inflater=LayoutInflater.from(context);//将xml布局转换为view对象,找到xml布局View v=inflater.inflate(layoutId,null);ImageView imageView=v.findViewById(R.id.iv_icon);TextView textView=v.findViewById(R.id.tv_name);//将数据放到相应的控件上imageView.setImageResource(image);textView.setText(name);return v;}}

2、ListActivity.java 调用适配器完成存储

 public class ListActivity extends AppCompatActivity {private ListView l1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_list);l1=findViewById(R.id.l1);//创建一个List对象ArrayList list=new ArrayList();list.add(new Planet("太阳",R.mipmap.ty));list.add(new Planet("水星",R.mipmap.sx));list.add(new Planet("金星",R.mipmap.jx));list.add(new Planet("地球",R.mipmap.dq));list.add(new Planet("火星",R.mipmap.hx));list.add(new Planet("木星",R.mipmap.mx));list.add(new Planet("土星",R.mipmap.tx));list.add(new Planet("天王星",R.mipmap.twx));list.add(new Planet("海王星",R.mipmap.hwx));//自定义适配器MyAdapter adapter=new MyAdapter(this,list,R.layout.item_list);l1.setAdapter(adapter);}}

5.4 ViewHolder用法

ViewHolder通常出现在适配器里,为的是ListView滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升复用性,要按需填充并重新使用view来减少对象的创建。优化ListView的加载速度就要让convertView匹配列表类型,并最大程度上的重新使用convertView。

定义一个ViewHolder,将convetView的tag设置为ViewHolder,不为空时重新使用即可

    @Overridepublic View getView(int i, View view, ViewGroup viewGroup) {ViewHolder holder=null;if(view==null){//创建ViewHolder对象 承载的是每一个列表项的视图holder=new ViewHolder();//将列表项布局转为View对象LayoutInflater inflater=LayoutInflater.from(context);view=inflater.inflate(R.layout.item_jf,null);//获取控件holder.t1=view.findViewById(R.id.tv_name);holder.t2=view.findViewById(R.id.tv_describe);holder.b1=view.findViewById(R.id.tv_button);//Tag从本质上来讲是就是相关联的view的额外的信息,经常用来存储一些view的数据view.setTag(holder);}else{//放着控件引用的ViewHolder对象,可以去复用holder= (ViewHolder) view.getTag();}//取数据Description description=data.get(i);holder.t1.setText(description.getItname());holder.t2.setText(description.getZtname());return view;}//创建内部类public final class ViewHolder{public TextView t1;public TextView t2;public Button b1;}

6、单选及复选按钮

6.1 复选按钮(CheckBox)

1、继承关系及使用方法
CheckBox继承CompoundButton
android:checked 设置按钮的勾选状态 true/false
CompoundButton分为两个部分,左侧是勾选图标,右侧是选项文字
若将andriod:button的值设为“@null”,则可以去掉左侧的勾选图标
若不设置android:text的值,则仅有左侧的勾选图标,没有右侧的选项文字
2、activity_main.xml
采用线性布局水平排列,有几个按钮选项就设几个TextView

<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="你喜欢什么运动?"android:textColor="@color/black"android:textSize="20dp"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/t1"android:textSize="15dp"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/t2"android:textSize="15dp"/></LinearLayout><CheckBoxandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="跑步"android:id="@+id/cb1"/><CheckBoxandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="游泳"android:id="@+id/cb2"/>

3、MainActivity.java
实现CompoundButton.OnCheckedChangeListener 接口,重写onCheckedChanged()方法

public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {private TextView t1,t2;private CheckBox cb1,cb2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);t1=findViewById(R.id.t1);t2=findViewById(R.id.t2);cb1=findViewById(R.id.cb1);cb2=findViewById(R.id.cb2);cb1.setOnCheckedChangeListener(this);cb2.setOnCheckedChangeListener(this);}@Override//第一个参数是按钮对象,第二个参数是当前状态public void onCheckedChanged(CompoundButton compoundButton, boolean b) {switch (compoundButton.getId()){case R.id.cb1:if(b){t1.setText("A");}else {t1.setText("");}break;case R.id.cb2:if(b){t2.setText("B");}else {t2.setText("");}break;}}
}

6.2 单选按钮(RadioButton)

1、继承关系及使用方法
RadioButton继承CompoundButton
RadioButton通常与单选组合框RadioGroup配合使用,以实现单选按钮间的互斥功能,RadioGroup中可以包含多个RadioButton。而且RadioGroupLinearLayout的子类,可以通过android:orientation属性设置RadioButton的排列方式。
getCheckedRadioButtonId():获取当前选中的单选按钮ID

2、activity_main.xml

<RadioGroupandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/rg"android:orientation="vertical"><RadioButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/rb1"android:text="肯定真ikun"/><RadioButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/rb2"android:text="必是小黑子"/></RadioGroup>

3、MainActivity.java

public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener{private TextView t1;private RadioGroup rg;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);rg=findViewById(R.id.rg);t1=findViewById(R.id.t1);rg.setOnCheckedChangeListener(this);}@Override//第一个参数为RadioGroup对象,第二个参数为选中单选选项IDpublic void onCheckedChanged(RadioGroup radioGroup, int i) {switch (i){case R.id.rb1:t1.setText("A");break;case R.id.rb2:t1.setText("B");break;}}
}

7、Fragment碎片

7.1 认识Fragment

Fragment把屏幕划分为几个碎片,对界面进行模块化处理,是一种嵌入Activity的UI片段
一个Activity中可以包含多个Fragment,一个Fragment也可以在多个Activity中使用

7.2 添加Fragment

1、在布局文件中添加
将Fragment作为一个控件加入布局文件中
在标签中需要添加“android:name”属性,其值为Fragment的完整路径名

<fragmentandroid:id="@+id/fm2"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="2"android:name="com.example.newsdemo.BlankFragment2"/>

2、通过代码动态添加
在布局文件中加入一个布局容器FrameLayout

<FrameLayoutandroid:id="@+id/framelayout"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/>

在Activity中调用方法

public class BlankFragment2 extends Fragment {Button button;FragmentManager manager;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {//将布局转为view对象View view=inflater.inflate(R.layout.fragment_blank2, container, false);button=view.findViewById(R.id.b1);//获取FragmentManger对象manager=getActivity().getSupportFragmentManager();        button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//获取FragmentTransaction对象 Fragment事务FragmentTransaction transaction=manager.beginTransaction();BlankFragment fragment=new BlankFragment();//第1个参数:要把Fragment添加到哪个控件,第2个参数:要添加的Fragment对象//add方法添加碎片不会移除已经添加的碎片。但是replace会先清除所有碎片然后才添加新的碎片transaction.add(R.id.framelayout,fragment);transaction.commit();}});return view;}
}

7.3 Fragment的生命周期

由于Fragment不能独立存在,因此Fragment的生命周期直接受所在Activity 的影响。当在Activity中创建Fragment 时,Fragment 处于启动状态;当Activity暂停时,其上的所有Fragment都暂停;当Activity被销毁时,其上的所有Fragment 都被销毁。

以下5个生命周期方法是Fragment生命周期独有的方法:
onAttatch( ): Fragment 与Activity 建立关联时调用。
onCreate View( ):创建Fragment视图时调用,主要用于加载布局;在该方法返回后,会立即调用onViewCreate( )方法。
onActivityCreated( ): 在Activity 创建完毕后调用。
onDestroyView( ): Fragment关联的视图被销毁时调用。
onDetach( ): Fragment和Activity 解除关联时调用。

8、SQLite数据库

8.1 认识SQLite数据库

SQLite是一种轻量级的关系型数据库,运行速度快,占用资源少,特别适合在移动设备上使用。
SQLite数据库支持标准的SQL语法,但比一般的数据库简单,不需要安装,不需要设置用户名和密码就可以使用。

8.2 SQLite数据库的创建

要创建SQLite数据库,需要先创建一个类继承SQLiteOpenHelper类,在该类中重写onCreate( ) 和 OnUpgrade( ) 方法。

1、下面我们创建一个名为“UserManager.db”数据库,并在此库中创建一张“users”表,存放用户信息

MyDataBaseHelp.ava

public class MyDataBaseHelp extends SQLiteOpenHelper {//将建表语句定义为一个字符串常量public static final String CREATE_USERS="create table users("+"id integer primary key autoincrement,"+"username text,"+"password text,"+"age integer)";private Context context;//第一个参数:上下文,第二个参数:数据库名,第三个参数:在查询数据时返回一个自定义Cursor 一般为null,第四个参数:当前数据库版本号public MyDataBaseHelp(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);this.context=context;}//创建数据库@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_USERS);//执行建表语句Toast.makeText(context,"数据库创建完毕",Toast.LENGTH_LONG).show();}
}

2、创建MyDataBaseHelper对象,调用 getReadableDatabase( ) 或 getWritableDatabase( ) 方法,创建数据库

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {private MyDataBaseHelp dataBaseHelp;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);dataBaseHelp=new MyDataBaseHelp(this,"UserManager.db",null,1);dataBaseHelp.getWritableDatabase();}
}

8.3 SQLite数据库的升级

在原有users表的基础上,再增加部门表department,进行数据库的更新(可以只看方法三

方法一:在onCreate( )方法,执行department建表语句

public class MyDataBaseHelp extends SQLiteOpenHelper {public static final String CREATE_USERS="create table users("+"id integer primary key autoincrement,"+"username text,"+"password text,"+"age integer)";public static final String CREATE_DEPARTMENT="create table department("+"id integer primary key autoincrement,"+"departmentname text,"+"departnamecode text)";private Context context;public MyDataBaseHelp(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);this.context=context;}//创建数据库@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_USERS);//执行建表语句db.execSQL(CREATE_DEPARTMENT);Toast.makeText(context,"数据库创建完毕",Toast.LENGTH_LONG).show();}
}

运行程序,可以发现没有弹出“数据库创建成功”的提示,没有创建department表,这是因为程序运行过,数据库就已经存在了,onCreate( )方法不会再执行,除非删除数据库,才会再次执行,显然这种方法是不合理的,所以我们可以用 onUpgrade( )升级方法。

方法二:在 onUpgrade( )方法中,进行数据库的更新

public class MyDataBaseHelp extends SQLiteOpenHelper {//省略@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {db.execSQL("drop table if exists users");db.execSQL("drop table if exists department");onCreate(db);}
}

执行两条drop语句,如果两个表都存在,就删除,然后调用onCreate( )方法重新创建表,这样可以避免重新创建时因表存在而导致程序报错
执行时,在创建MyDataBaseHelper对象时传入当前数据库版本号(比旧版本号大就行

public class MainActivity extends AppCompatActivity implements View.OnClickListener {private MyDataBaseHelp dataBaseHelp;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);dataBaseHelp=new MyDataBaseHelp(this,"UserManager.db",null,2);dataBaseHelp.getWritableDatabase();}
}

但是这种方法会将原数据表删除,会使存储的本地数据全部丢失,所以还是看更好的方法三吧

方法三:只要指定的数据库版本号大于当前的版本号,就会进入onUpgrade( )方法,对当前数据库版本号进行判断,在执行相应的数据库更新操作

public class MyDataBaseHelp extends SQLiteOpenHelper {//省略@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {switch (oldVersion){case 1:db.execSQL(CREATE_DEPARTMENT);}}
}

通过switch判断当前版本号是1,就会只创建department表,如果有第3个版本数据库更新,就添加新的case语句,判断当前版本号为2.
注意
1、activity和dao方法中的传参也要跟着变
2、case语句后没有break,这样可以在跨版本升级时,每一次数据库的修改语句都能全部执行

8.4 SQLite数据库的查看

数据库的存储位置与SharedPreferences相同,在datda/data/包名/目录下,查看数据可以使用Android调试桥(adb),存放在SDKplatform-tools目录下,可以用cmd打开

步骤一:配置环境变量
将platform-tools目录添加到环境变量中系统变量的Path中

步骤二:在cmd中输入”adb shell“命令,进入设备控制台

步骤三:使用cd命令,转到data/data/包名/databases目录下

若出现上图中的”Permission denied“,则表示没有查看系统的权限,要通过”su root“命令,更换系统用户

步骤四:使用ls命令,查看该目录下的文件

步骤五:输入”sqlite3 数据库名“,打开数据库

输入”.table“命令,可以查看数据库中的表,通过”.schema“命令可查看建表语句,也可用sql语句进行数据库操作

步骤六:输入”.quit“退出数据库调试,回到adb,输入”exit“命令退出设备控制台

8.5 SQLite数据库的基本操作

在这里我补充一个对数据进行增、删、改、查的案例,以users表为例
1、创建MyDataBaseHelper继承SQLiteOpenHelper,创建User实体类,在activity_main.xml完成布局,此处不再赘述

2、创建UserDao类,封装增、删、改、查方法

public class UserDao {private MyDataBaseHelp dataBaseHelp;public UserDao(Context context){dataBaseHelp=new MyDataBaseHelp(context,"UserManager.db",null,2);}//添加数据public long addUser(User user){//1.获取数据库对象SQLiteDatabase db=dataBaseHelp.getWritableDatabase();ContentValues values=new ContentValues();//key:数据表的列名,value:值values.put("username",user.getUsername());values.put("password",user.getPassword());values.put("age",user.getAge());//第一个参数:表名,第二个参数:自动赋值为null的列名,第三个参数:数据//返回值:long,返回行号,如果添加不成功,返回-1long id=db.insert("users",null,values);//数据库关闭db.close();return id;}//查询数据public ArrayList queryUser(){ArrayList list=new ArrayList();SQLiteDatabase db=dataBaseHelp.getWritableDatabase();//query的参数对应于select查询sql语句中的各个部分//db.query("users",new String[]{"id","username","password","age"},"id=?",new String[]{id},null,null,null);//db.rawQuery();//接受sql语句作为参数Cursor cursor=db.query("users",null,null,null,null,null,null);//遍历cursor将数据放到list中list=convertFromCursor(cursor);return list;}private ArrayList convertFromCursor(Cursor cursor){ArrayList list=new ArrayList();//有没有返回值,是否查到结果,如果true,则有if(cursor!=null&&cursor.moveToFirst()){do{int id=cursor.getInt(cursor.getColumnIndexOrThrow("id"));String username=cursor.getString(cursor.getColumnIndexOrThrow("username"));String password=cursor.getString(cursor.getColumnIndexOrThrow("password"));int age=cursor.getInt(cursor.getColumnIndexOrThrow("age"));User user=new User(id,username,password,age);list.add(user);}while (cursor.moveToNext());//true还有数据,继续遍历}else{list=null;}return list;}//修改数据public int updateUser(User user){SQLiteDatabase db=dataBaseHelp.getWritableDatabase();ContentValues values=new ContentValues();values.put("password",user.getPassword());values.put("age",user.getAge());int i=db.update("users",values,"username=?",new String[]{user.getUsername()});db.close();return i;}//删除数据public int deleteUser(User user){SQLiteDatabase db=dataBaseHelp.getWritableDatabase();int n=db.delete("users","username=?",new String[]{user.getUsername()});db.close();return n;}
}

3、在MainActivity中编写逻辑代码,实现增、删、改、查功能

public class MainActivity extends AppCompatActivity implements View.OnClickListener {private EditText et_username,et_password,et_age;private Button bt_save,bt_query,bt_update,bt_delete;private TextView tv_show;private MyDataBaseHelp dataBaseHelp;private UserDao userDao;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);dataBaseHelp=new MyDataBaseHelp(this,"UserManager.db",null,2);dataBaseHelp.getWritableDatabase();userDao=new UserDao(this);init();}public void init(){et_username = findViewById(R.id.et_username);et_password = findViewById(R.id.et_password);et_age = findViewById(R.id.et_age);bt_save = findViewById(R.id.bt_save);bt_query = findViewById(R.id.bt_query);bt_update = findViewById(R.id.bt_update);bt_delete = findViewById(R.id.bt_delete);tv_show = findViewById(R.id.tv_show);bt_save.setOnClickListener(this);bt_query.setOnClickListener(this);bt_update.setOnClickListener(this);bt_delete.setOnClickListener(this);}@Overridepublic void onClick(View view) {switch (view.getId()) {//保存数据case R.id.bt_save:String uname= et_username.getText().toString();String psw= et_password.getText().toString();int age=Integer.parseInt(et_age.getText().toString());User u=new User(uname,psw,age);long id=userDao.addUser(u);if(id!=-1){Toast.makeText(this,"保存成功",Toast.LENGTH_LONG).show();}else{Toast.makeText(this,"保存失败",Toast.LENGTH_LONG).show();}break;//查询数据case R.id.bt_query:ArrayList users= userDao.queryUser();StringBuffer stringBuffer=new StringBuffer();if(users.size()==0){tv_show.setText("无数据");}else{for(int i=0;i<users.size();i++){User u1= (User) users.get(i);stringBuffer.append("ID: "+u1.getId() +"   用户名: "+u1.getUsername() +"   密码: "+u1.getPassword() +"   年龄: "+u1.getAge() +"\n");}tv_show.setText(stringBuffer);}break;//修改数据case R.id.bt_update:String uname1=et_username.getText().toString();String psw1=et_password.getText().toString();int age1=Integer.parseInt(et_age.getText().toString());User u1=new User(uname1,psw1,age1);int i=userDao.updateUser(u1);if(i!=0){Toast.makeText(this,"修改成功",Toast.LENGTH_LONG).show();}else{Toast.makeText(this,"修改失败",Toast.LENGTH_LONG).show();}break;//删除数据case R.id.bt_delete:String uname2=et_username.getText().toString();User u2=new User(uname2);int n= userDao.deleteUser(u2);if(n!=0){Toast.makeText(this,"删除成功",Toast.LENGTH_LONG).show();}else{Toast.makeText(this,"删除失败",Toast.LENGTH_LONG).show();}break;}}
}

注意:除了以上方法,还可以用SQL语句对数据库进行增、删、改、查操作

 //增db.execSQL("insert into users(username,password) values(?,?)",new Object[]{name,password});//删db.execSQL("delete from users where id=1");//改db.execSQL("update users set password=? where username=?",new Object[]{password,username});//查Cursor cursor=db.rawQuery("users",new String[]{"id","username","password","age"},"id=?",new String[]{id},null,null,null);

Android移动应用开发相关推荐

  1. android sdk软件开发套件,ANDROIDSDK-SITARA

    TI 的 Android 开发套件是一套完整的软件,Sitara 器件的开发人员可以用其轻松快速地评估 Android 操作系统.该套件提供稳定且经全面测试的软件基础,可广泛用于包括评估模块和 Bea ...

  2. 树莓派Android Things物联网开发:创建一个Things项目

    [转载请注明出处:http://blog.csdn.net/leytton/article/details/77854144] <树莓派Android Things物联网开发>系列文章专栏 ...

  3. Android移动APP开发笔记——最新版Cordova 5.3.1(PhoneGap)搭建开发环境

    引言 简单介绍一下Cordova的来历,Cordova的前身叫PhoneGap,自被Adobe收购后交由Apache管理,并将其核心功能开源改名为Cordova.它能让你使用HTML5轻松调用本地AP ...

  4. 【Android】Parse开发笔记(1)—— 准备

    一.简介 Parse是由 YC 孵化出来的.专为移动应用提供后台服务的云计算平台,为开发者包办繁琐的后台服务,让开发者只需专注于具体的开发工作.它提供任意数据保存.照片或其它文件存储.发送推送通知.创 ...

  5. Android短视频开发都需要什么技术?

    今天我们来讲点干货,估计来看这篇帖子的人都知道短视频APP有多火,也都知道安卓系统在手机系统中占的市场份额有多大,那我就不多嘴巴拉巴拉一些行业背景了,以下我着重讲一讲Android端的短视频开发技术. ...

  6. Android Studio ndk-Jni开发详细

    2019独角兽企业重金招聘Python工程师标准>>> Android Studio ndk-Jni开发详细入门,Aes加密demo 字数920 阅读13 评论0 喜欢0 Java ...

  7. android的UI开发工程师指引

    不管是MFC,还是linux,还是android,UI开发都是如下两大核心机制: 第一个是消息循环,第二个是界面组织结构. 围绕着这些,衍生出来的OpenGL,SurfaceView,SurfaceF ...

  8. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  9. android 编写系统应用,Android应用快速开发系统设计与实现

    摘要: 自Android系统诞生以来,传统的手持电话遭受了巨大冲击,智能手机的功能越来越强大,价格也越来越低廉,智能手机开始出现在越来越多的普通用户手中.到现在为止,Android手机已经在智能手机领 ...

  10. android应用程序开发_Kotlin与Flutter:Android跨平台应用程序开发,到底选择哪个?...

    移动互联时代--应用为王 移动互联网时代,很难想象没有应用程序的生活.从我们睁眼醒来的那一刻到我们真正睡觉的那一刻,无数的应用程序围绕着我们.根据统计,国人平均在移动设备上花费4个小时以上! 而这其中 ...

最新文章

  1. 百度开发者大会-《用HTML5新特性开发移动App》PPT分享
  2. 三关节机械臂控制需求说明压缩文件中的相关文档说明
  3. python开三次方_python实现三次样条插值
  4. 从零实现Vue的组件库(零)- 基本结构以及构建工具
  5. oracle rac 创建ocr,Oracle rac 11g在线添加ocr,votedisk
  6. arcgis重心迁移分析_【停课不停研ArcGIS制图微教程系列】土地利用分布图的制作——以温州市为例...
  7. 有趣的算法(八):3分钟看懂选择排序(C语言实现)
  8. Node:连接MySQL报错\lib\protocol\Parser.js:43 Cannot read property ‘query‘ of undefined
  9. ios 通知接收两次_苹果健康体系又进一步,iOS 14.3支持有氧适能通知
  10. Arduino - CHQ1838B红外接收模块控制LED实验(附.Tinkercad图形化编程)
  11. 手工内存管理规则的总结
  12. gmail注册方法_如何在Gmail中释放空间:5种回收空间的方法
  13. 【计算机视觉】关于计算机视觉(随谈)
  14. 前端拖拽时手型为禁用
  15. 科研用matlab还是python_科的解释|科的意思|汉典“科”字的基本解释
  16. 送什么礼物给小学生比较有纪念意义?适合送小学生的小礼物
  17. Linux 块设备层中的Multi-queue分析
  18. jabber技术概况
  19. 地理坐标系、大地坐标系、地图投影与重投影
  20. 快速上手golang

热门文章

  1. 火山PC百集基础教程(火山视窗)
  2. PowerPC的字节序问题
  3. html网页加减乘除代码,html+js实现简单的计算器代码(加减乘除)
  4. python爬取微信群聊内容_再不学Python 你就被同龄人甩开了吗?
  5. A-286热加工/锻造
  6. 今天咱们用Python整一个植物大战僵尸游戏 | 附带源码
  7. kafka 修改分区_Kafka动态调整topic分区partition - russle的专栏 - CSDN博客
  8. 微信小程序实战教程1503---生成二维码
  9. MDN的HTML入门,关于MDN,HTML入门来自MDN文档
  10. 2016年之前目标跟踪算法总结