Android学习笔记
安装Androidstudio注意事项:
Androidstudio常用快捷键:https://www.cnblogs.com/kangyi/p/4246117.html
Androidstudio常用插件:https://www.open-open.com/lib/view/open1480329318348.html
Androidstudio常用设置:https://blog.csdn.net/weixin_39251617/article/details/79869586
Androidstudio真机调试时出现mainSDK(API 28)>devicesdk(API 25): https://blog.csdn.net/languobeibei/article/details/78293497
Androidstudio SDK开发帮助文档:http://www.pansoso.com/d/225046/
开发前的配置
配置build.gradle(Module:app): 版本间关系: minSdkVersion <= targetSdkVersion <= compileSdkVersion <= buildToolsVersion 理想版本关系: minSdkVersion <= targetSdkVersion == compileSdkVersion == buildToolsVersion: apply plugin: 'com.android.application' android { compileSdkVersion 26 buildToolsVersion "28.0.3" defaultConfig { applicationId "com.helloworld.lq.helloworld" minSdkVersion 22 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.+' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
添加gradle:file:///C:/Users/Administrator/.gradle/wrapper/dists/gradle-4.6-all/bcst21l2brirad8k2ben1letg/gradle-4.6-all.zip
(一)目录文件:
\Hello\app\build\generated\not_namespaced_r_class_sources\debug\processDebugResources\r\com\example\hello\R.java文件不可修改,res文件下 的资源会在R.java中自动生成id(使用src文件中的资源直接引用R.xxx)几个内部类
\Hello\app\src\main\res\drawable:放置图片(不同的分辨率)
\Hello\app\src\main\res\layout文件:为activity配置布局
\Hello\app\src\main\res\values文件:放置键值对(为国际化语言考虑)
\Hello\app\src\main\AndroidManifest.xml文件是配置整个应用程序
<android:icon配置应用程序的图标。。。
<android:label配置应用程序的标签。。。
配置activity:
<activity android:name=".Hello1Activity"></activity> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
//首先启动某个activity添加的代码:
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
(二)Activity
1,作用:可见的,用户和应用程序之间的交互接口,放置不同的控件(控件的容器)
2,activity要点:
①activity是一个类,需要继承Activity
②需要复复写onCreate()方法
③AndroidManifest.xml文件中会出现activity配置
④
3,多个activity的关系
Component name:指定一个请求跳转到另一个activity的名字
Action:指定跳转的activity的行为(如Intent.ACTION_SENDTO是一个发短信的行为)
Date:传递的数据(uri类型)
Extras:放置一些键值对
//点击MainActivity的按钮,跳转到Hello1Activity
package com.example.hello; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private Button bt_a; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_a=(Button) findViewById(R.id.bt_a); bt_a.setOnClickListener(new Bt_aListener()); } class Bt_aListener implements View.OnClickListener//设置按钮的监听器,实现跳转功能 { @Override public void onClick(View v) { Intent intent=new Intent(); intent.setClass(MainActivity.this, Hello1Activity.class); MainActivity.this.startActivity(intent);//传参 } }
package com.example.hello;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class Hello1Activity extends AppCompatActivity {
private TextView tv_b=null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello1);
/* Intent intent=getIntent();
String data=intent.getStringExtra("data1");*/
tv_b=(TextView) findViewById(R.id.tv_b);
//tv_b.setText(data);
tv_b.setText(R.string.HelloActivity);
}
}
4,用intent在activity之间传递数据(两个Activity可能不是在一个应用程序中)
(1),从MainActivity向HelloActivity传递参数123
package com.example.hello; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { private Button bt_a; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_a=(Button) findViewById(R.id.bt_a); bt_a.setOnClickListener(new Bt_aListener()); } class Bt_aListener implements View.OnClickListener { @Override public void onClick(View v) { Intent intent=new Intent(); intent.putExtra("data1", "123"); intent.setClass(MainActivity.this, Hello1Activity.class); MainActivity.this.startActivity(intent); } } }
package com.example.hello;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class Hello1Activity extends AppCompatActivity {
private TextView tv_b=null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello1);
Intent intent=getIntent();
String data=intent.getStringExtra("data1");
tv_b=(TextView) findViewById(R.id.tv_b);
tv_b.setText(data);
//tv_b.setText(R.string.HelloActivity);
}
}
(2)用MainActivity实现发短信功能:
package com.example.hello; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { private Button bt_a; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_a=(Button) findViewById(R.id.bt_a); bt_a.setOnClickListener(new Bt_aListener()); } class Bt_aListener implements View.OnClickListener { @Override public void onClick(View v) //必须重写这个方法 { /* Intent intent=new Intent(); intent.putExtra("data1", "123"); intent.setClass(MainActivity.this, Hello1Activity.class); MainActivity.this.startActivity(intent);*/ Uri uri=Uri.parse("smsto://0800000123"); Intent intent=new Intent(Intent.ACTION_SENDTO,uri ); intent.putExtra("data2", "欢迎使用!"); startActivity(intent); } } }
5,activity中常见的控件;
(1),TextView:文本信息
(2),ExitText:可编辑的文本框
(3),Button:按钮
(4),meno:菜单
初始化一个菜单(当用户点击菜单按钮调用此方法)
@Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, 1,1 , R.string.menu_a); //add(当前组的id,菜单小块item的id,当前菜单中小块排序的id,小块显示的值) menu.add(0, 1,2 , R.string.menu_b); return super.onCreateOptionsMenu(menu); }
当用户点击菜单中的某个item时:
@Override public boolean onOptionsItemSelected(MenuItem item) { int id=item.getItemId(); if(id==1) { finish(); } return super.onOptionsItemSelected(item); }
(5)练习做一个实现两个数相乘的APP
①.java代码:
//MainActivity.java package com.example.hello; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView tv; private EditText et_a; private EditText et_b; private Button bt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)findViewById(R.id.tv); et_a=(EditText)findViewById(R.id.et_a); et_b=(EditText)findViewById(R.id.et_b); bt=(Button)findViewById(R.id.bt); //bt.setText("计算"); //tv.setText("乘以(X)"); tv.setText(R.string.tv); bt.setText(R.string.bt); bt.setOnClickListener(new BtListener()); } @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, 1,1 , R.string.menu_a); //add(当前组的id,菜单的id,当前菜单中小块排序的id,小块显示的值) menu.add(0, 1,2 , R.string.menu_b); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { int id=item.getItemId(); if(id==1) { finish(); } return super.onOptionsItemSelected(item); } class BtListener implements View.OnClickListener { @Override public void onClick(View v) { Intent intent=new Intent(); String et_astr=et_a.getText().toString(); String et_bstr=et_b.getText().toString(); intent.putExtra("et_a", et_astr); intent.putExtra("et_b", et_bstr); intent.setClass(MainActivity.this,Hello1Activity.class ); MainActivity.this.startActivity(intent); } } } //HelloActivity.java package com.example.hello; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; public class Hello1Activity extends AppCompatActivity { private TextView tv_b; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_hello1); tv_b=(TextView)findViewById(R.id.tv_b); Intent intent=getIntent(); String et_astr=intent.getStringExtra("et_a"); String et_bstr=intent.getStringExtra("et_b"); int et_ain=Integer.getInteger(et_astr); int et_bin=Integer.getInteger(et_bstr); int result=et_ain*et_bin; tv_b.setText(result+ " " ); //setText(必须是字符串类型) } } //
②.xml代码:
//activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" tools:context=".MainActivity"> <EditText android:id="@+id/et_a" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="wrap_content" /> <EditText android:id="@+id/et_b" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/bt" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#00f" /> </LinearLayout> //activity_hello1.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Hello1Activity"> <TextView android:id="@+id/tv_b" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> //string.xml <resources> <string name="app_name">Hello</string> <string name="HelloActivity">HelloActivity!</string> <string name="tv">乘以(X)</string> <string name="bt">计算</string> <string name="menu_a">后退</string> <string name="menu_b">关于</string> </resources>
③activity配置文件
//AndroidMainifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.hello"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".Hello1Activity"> </activity> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
④出现的问题:不知道怎么回事,在真机上调试activity之间的跳转出现闪退现象。
6,Activity的生命周期函数(当手机内存不足时调用onPause(),onStop(),onDestroy()方法的Activity会被kill掉):
(1)首先是创建activity,也就是onCreate()方法,关于这个方法,官方文档描述为:第一种创建该activity时调用,主要完成静态数据的初始化等,还提供一个含有该activity自 己“冻结”的状态的Bundle对象;该方法常常后面会伴随onStart()方法。
(2)onStart()方法:当该activity对用户可见的时候调用
(3)onResume()方法:当activity可以获取焦点时调用(也就是该activity是栈顶activity的时候);
(4)onStop()方法:该方法适合onStart()方法对应的方法,即当该activity不可见的时候调用
(5)onPause()方法:当activity不可以获取焦点时调用(也就是该activity不是栈顶activity的时候);
(6)onDestroy()方法:当该activity销毁的时候调用(通常会在这里放一些解绑服务,取消广播注册的操作);
还有一个用得较少:
(7)onRestart()方法:当你的activity执行了onStop()之后,又想实现onStart()的效果,这个时候就会执行该方法
图示:
启动第一个Activity:
从第一个Activity启动第二个Activity:(当第二个Activity完全遮掩第一个Activity时)若第二个Activity以小窗口形式将第一个Activity遮掩一部分,则不调用FirstActivity的onStop()方 法。
从第二个Activity返回到第一个Activity:
。SecondActivity
-onPause()
.FirstActivity
-onRestart()
.FirstActivity
-onStart()
.FirstActivity
-onResume()
.SecondActivity
-onStop()
.SecondActivity
-onDestroy():通常在调用finish()方法或当前内存不足时调用
Task(任务)以栈的形式运行过程:
打开第一个Activity,第一个Activity被压入其中,启动第二个Activity,第二个Activity被压入其中,手机显示最上面的Activity...
当点击返回上面的Activity依次被取除。
注意:当将第二个Activity中的按钮监听器中的startActivity(Intent)替换为finish(),则只会影响返回时的效果,在第三个Activity显示时点击返回,会直接返回到第一个Activity。
SQLite数据库(可嵌入,程序驱动)访问:
SharedPreferenced的使用方法:SharedPreferences 是一个轻量级的存储类,主要是保存一些小的数据,一些状态信息
第一步:初始化
* 获取SharedPreferenced对象
* 第一个参数是生成xml的文件名,第二个参数是存储的格式,SharedPreferences preferences = getSharedPreferences("OpenCount", Context.MODE_PRIVATE);
第二步:获取edit对象
//获取到edit对象,SharedPreferences.Editor edit = preferences.edit();
第三步:通过edit对象写入数据,第一个参数是属性名,第二个参数是所要传的值
通过editor对象写入数据,edit.putInt("count",1);
第四步:将数据保存到xml文件里,提交数据存入到xml文件中,edit.commit();
第五步:通过get方法读取所存的信息
int count = preferences.getInt("count", 0);
SharedPreferences这个方法可以将数据存入到本地文件,用来存储登录次数,和登录信息等各种信息
SetFilters对输入框格式,字符数的控制:
(1) et_vcode.setFilters(new InputFilter[ ]);参数是一个InputFilter类型的数组
(2)如果直接添加限制字数的规则,直接newLengthFilter就可以了,例如限制输入最大不超过16位:et_vcode.setFilters(new InputFilter[ ]{new InputFilter.LengthFilter(16)});
(3)如果此时你还有另一个规则,例如只能输入a-z的小写字母,直接在InputFilter数组中添加 : et_vcode.setFilters(newInputFilter[{ codeInputFilter , newInputFilter . LengthFilter(16)});
(4) codeInputFilter继承InputFilter,规则自己定义,重写里面的public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {}
filter参数介绍:
source :变化的字符串
start :变化字符的首字符下标
end :变化字符的尾字符下
dest :带光标的字符串
dstart :光标的起始位置
dend :光标的结束位置
filter方法返回的是一个CharSequence,用来控制可编辑控件添加字符时的约束条件。
主要分为三种情况:返回null,表示可正常添加source字符串;返回"",表示不变动原字符;返回以上之外的字符串,表示将返回的该字符串追加到远字符串中。
例如:
edit_register.setFilters(new InputFilter[] //设置输入格式 { new InputFilter() { @Override public CharSequence filter(CharSequence source, int start, int end,Spanned dest, int dstart, int dend) { for (int i = start; i < end; i++) { if (!Character.isLetterOrDigit(source.charAt(i)) && !Character.toString(source.charAt(i)).equals("_")) { Toast.makeText(Register_Activity.this, "只能使用'_'、字母、数字、汉字注册!", Toast.LENGTH_SHORT).show(); return ""; } } return null; } } })
方法:onEditorAction(TextView textView,int actionId,KeyEvent keyEvent)的用法:
* 第一个参数:TextView textView 表示当前触发事件的EditText的对象,类似于textView=findViewById(R.id.edit_account)
* 第二个参数:int actionId 表示 按下“完成按钮”,这里和xml文件中EditText属性imeOptions对应
actionId的取值:
imeOptions=”actionUnspecified” –> EditorInfo.IME_ACTION_UNSPECIFIED
imeOptions=”actionNone” –> EditorInfo.IME_ACTION_NONE
imeOptions=”actionGo” –> EditorInfo.IME_ACTION_GO
imeOptions=”actionSearch” –> EditorInfo.IME_ACTION_SEARCH
imeOptions=”actionSend” –> EditorInfo.IME_ACTION_SEND
imeOptions=”actionNext” –> EditorInfo.IME_ACTION_NEXT
imeOptions=”actionDone” –> EditorInfo.IME_ACTION_DONE (如果编辑信息输入完成 )
* 但要注意actionId是指软盘上的,而键盘上的actionId与软盘上的不一样;即在软盘上“完成按钮”的actionId为0,
* 而键盘上的“完成按钮(回车键)”的actionId为6
* 第三个参数:KeyEvent keyEvent 表示 按下“完成按钮”,这里和xml文件中EditText属性imeOptions对应,但keyEvent里面的内容更丰富,内容如下:
* keyEvent.toString()=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ENTER,
* scanCode=28, metaState=0, flags=0x8, repeatCount=0, eventTime=5664212, downTime=5664212, deviceId=1, source=0x301 }
* 返回值:返回true,保留软键盘;false,隐藏软键盘
InputMethodManager imm =(InputMethodManager) getSystemService(Login_Activity.this.INPUT_METHOD_SERVICE); //调用系统服务(包括显示键盘,隐藏键盘) imm.hideSoftInputFromWindow(edit_password.getWindowToken(), 0); //隐藏键盘
对输入的密码显示,隐藏操作:
boolean flag=false;
if (flag == true) {//不可见 edit_password.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); //显示密码 flag = false; openpwd.setBackgroundResource(R.drawable.invisible); }
else
{ edit_password.setTransformationMethod(PasswordTransformationMethod.getInstance()); //隐藏密码 flag = true; openpwd.setBackgroundResource(R.drawable.visible); }
TextUtils.isEmpty(CharSequence str)这个方法是系统为我们提供的一个非常方便的判断一个CharSequence类型的
参数是否为空的方法,这个方法的返回值是一个boolean,当括号内参数为(null)或者("")时,返回true。
TextUtils.equals(CharSequence str1, CharSequence str2)这个是比较括号内两个CharSequence类型的参数是否相等