看的书叫:第一行代码 第二版 ,在微信读书(APP)上可以免费看
用的是:Android Studio
遇到的问题
1.Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8. jdk要用11。8不可以哦。 解决: File > Settings > 搜索 Gradle > 选择我们需要的版本 > Apply > ok 2.Gradle sync failed: Cause: startup failed: 网太差,更新gradle的地址很慢或者写错了,使得他每次加载项目的时候没办法更新gradle 下载地址: distributionUrl=https://downloads.gradle-dn.com/distributions/gradle-7.0.3-bin.zip 解决:到这个地址下载好,然后本地运行已经下载好的就行。 或者找个网好的地方新建项目。。。
笔记
一、 log日志工具
(log是很好用的调试工具!) TAG:“一般是类名,或者是自定义的过滤器tag” Log.d(TAG, “信息”); 在logcat里搜信息,就能找到log记录 这这里可以自定义过滤器
快捷方式: debug:logd+tab:Log.d(); 除了debug还有verbose、info、warn、error logt+tab可以快捷创建tag的局部变量 private static final String TAG = “类名”;
二、Activity活动
活动的基本用法
创建按钮
1.新建按钮页面文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/button_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="button_1" />
</LinearLayout>
2.在活动中加载布局
setContentView(R.layout.first_layout);//加载页面
3.在AndroidManifest文件中注册活动
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<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/Theme.MyApplication">
<activity
android:name=".MainActivity"
android:label="this is FirstActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
创建Toast-按下按钮弹出Toast
1.按钮实例化 2.注册监听器
public class MainActivity extends AppCompatActivity {
private static final String TAG = "data";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);
Button button_1 = (Button) findViewById(R.id.button_1);
Log.d(TAG, "onCreate execute");
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"you clicked Button_1", Toast.LENGTH_SHORT).show();
}
});
}
}
创建菜单-使用菜单menu
1.先在 XML 中定义一个菜单。新建menu文件夹,新建main.xml; 在main.xml文件中建立选项按键。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="Add"/>
<item
android:id="@+id/remove_item"
android:title="Remove"/>
</menu>
2.让菜单显示出来,在Activity中重写onCreateOptionsMenu()方法。 重写快捷键ctrl+o
- MenuInflater :用来解析定义在menu 目录下的菜单布局文件的
- Inflate():就是将xml定义的一个布局找出来
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
通过getMenuInflater()方法获取获取MenuInflater对象,在调用inflate方法就可以为活动创建当前对象了。
inflater()方法接受两个参数,第一个是我们通过制定哪一个资源文件来创建菜单,这里传入R.menu.main;第二个用于指定我们的菜单项将添加到那一个Menu对象中,这里直接使用onCreateOptionsMenu()方法中的menu对象。
最后返回true 显示出来,如果返回false则不显示。
3.定义菜单响应事件 重写onOptionsItemSelected
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.add_item:
Toast.makeText(this, "You click add", Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this, "You click Remove", Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
销毁一个活动
按下手机上的back即可 自由用代码的方式:修改按钮监听器里的代码如下:
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
finish();
}
});
使用Intent在活动穿梭
点击应用图标后只能进入主活动,如何从主活动跳转到其他活动呢? intent 英:目的 意图
使用显式Intent进行跳转
Intent(上下文,想要启动的目标活动) 在上下文下打开想要启动的目标活动 Intent(Context packageContext, Class<?> cls)
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
Intent(MainActivity.this,SecondActivity.class); 在MainActivity这个上下文下打开SecondActivity这个活动
使用隐式Intent进行跳转
在Manifest.xml配置文件中配置intent-filter过滤器节点,给目标活动配置(跳转目标)
<activity
android:name=".SecondActivity"
android:exported="false"
android:label="this is SecondActivity">
<intent-filter>
<action android:name="a" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
就像暗号,俩都是a,所以匹配上了 给触发按钮设置监听
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent("a");
startActivity(intent);
}
});
只有当action、category都匹配上,才能成功。
刚才只有一个action,能成功是因为category用的是默认的,接下来也同样配置一下category。
<activity
android:name=".SecondActivity"
android:exported="false"
android:label="this is SecondActivity">
<intent-filter>
<action android:name="a" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="b" />
</intent-filter>
</activity>
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent("a");
intent.addCategory("b");
startActivity(intent);
}
});
更多隐式Intent用法
展示一个网页
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.baidu.com"));
startActivity(intent);
}
});
intent的action是Intent.ACTION_VIEW,这是一个系统内置的动作。 setData()用于指定intent正在操作的数据,接收的是url。
调用系统拨号
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
});
使用Intent传递数据
传递数据给下一个活动
使用intent.putExtra(键,值)存放字符串,extra 英:附加物 使用intent.getStringExtra(键)获取字符串
(MainActivity)现在把字符串hello从FirstActivity传递到SecondActivity:
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("extra_data","hello");
startActivity(intent);
}
});
(SecondActivity)接收字符串:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
}
}
返回数据给上一个活动
在ActivityA中用startActivityForResult()方法启动了Activity B,并且在B中通过setResult()方法给A返回数据,A使用onActivityResult回调函数接收数据。 1.在ActivityA中用startActivityForResult()方法启动了Activity B (MainActivity)
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
}
});
在启动另外一个Activity的时候,有两种方法: 一种就是直接使用startActivity, 另一种是使用startActivityForResult。 startActivityForResult的主要作用就是它可以回传数据。
startActivityForResult(Intent intent, int requestCode);
-
第一个参数:一个Intent对象,用于携带将跳转至下一个界面中使用的数据,使用putExtra(A,B)方法,此处存储的数据类型特别多,基本类型全部支持。 -
第二个参数:请求码,为了区分启动不同的Intent,或者传递不同的数据使用,作为一种不同启动的标识。如果> =0,当Activity结束时requestCode将归还在onActivityResult()中。以便确定返回的数据是从哪个Activity中返回。
2.在B中通过setResult()方法给A返回数据
(SecondActivity)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Button button_2 = (Button) findViewById(R.id.button_2);
button_2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra("return_data","hello");
setResult(RESULT_OK,intent);
finish();
}
});
}
setResult(RESULT_OK,intent)
- 第一个参数:RESULT_OK 用于向上一个活动返回处理结果。
- 第二个参数:intent,用于携带数据。
3.A页面接收B返回来的数据 (MainActivity)
@SuppressLint("MissingSuperCall")
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
String returnData = data.getStringExtra("return_data");
Log.d("MainActivity", returnData);
}
break;
default:
}
}
onActivityResult(int requestCode, int resultCode, Intent data)
- 第一个参数:requestCode 请求码 (哪个活动发出请求的标识)。
- 第二个参数:resultCode 处理结果(RESULT_OK)。
- 第三个参数:data 返回的intent数据。
成功返回数据
如果用户通过手机的back键返回到A页面,可以重写onBackPressed(): (SecondActivity)
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("return_data","hello 你按了back");
setResult(RESULT_OK,intent);
finish();
}
活动的生命周期
活动的生存期
Activity类定义了7个回调方法。
(1)onCreate():在活动第一次被创建的时候调用。在这个方法中完成活动的初始化操作,例如加载布局、绑定事件等
(2)onStart():在活动由不可见变成可见的时候调用。
(3)onResume():在活动准备好和用户进行交互的时候调用。此时活动位于返回栈的栈顶,并且处于运行状态。
(4)onPause():在系统准备去启动或者恢复另一个活动的时候调用。在该方法中将一些销毁CPU的资源释放掉,保存关键数据。该方法执行速度一定要快,不然会影响栈顶活动的使用
(5)onStop():在方法完全不可见的时候调用。注意onStop()与onPause()的区别。
(6)onDestroy():在活动被销毁之前调用。
(7)onRestart():在活动由停止状态变为运行状态前调用。 该图片出自https://blog.csdn.net/u013476556/article/details/44976947
内存不足,数据恢复
内存不足可能回收stop时的活动,临时数据会丢失,用户会生气。 解决: onSaveInstanceState()回调函数,保证回收之前一定被调用。
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("data_key","临时数据");
}
这样就保存在Bundle对象里。 怎么恢复?每次onCreate()里面有Bundle参数,平时是null,如果回收前用onSaveInstanceState保存过的话,这个参数就会带之前保存过的数据,修改onCreate取出来即可。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
if(savedInstanceState != null){
String tempData = savedInstanceState.getString("data_key");
Log.d("SecondActivity", "tempData");
}
}
Bundle也可以用来传数据,先把数据存在Bundle,再存到intent。
活动的启动模式
修改活动的启动模式在AndroidManifest.xml中,launchMode = “模式”
<activity
android:name=".ThirdActivity"
android:launchMode="standard"
android:exported="true">
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http" />
</intent-filter>
</activity>
standard
默认模式,每启动一个活动,那个活动就会入栈,他也不在乎这个活动是否在栈里已存在,每次启动活动就会创建一个新的实例。
singleTop
栈顶单例,在启动活动时,发现返回栈的栈顶是这个活动,不会创建新的实例。如果栈顶不是这个活动,还是会创建新的实例的。
singleTask
启动活动时,检查有没有活动实例,如果有就直接用这个实例,然后把此活动之上的所有活动都出栈,没有的话就创建新的实例。
singleInstance
启用一个单独的新栈管理这个活动,解决共享活动实例问题。 销毁活动也是先销毁主栈,再清新栈。
技巧
知道当前活动是哪个
在当前活动的onCreate中写:
Log.d("MainActivity", getClass().getSimpleName());
可以在日志中看见。
随时随地退出程序
如果启动栈里有很多活动,现在想直接退出程序,按home也没用(只是挂起),可以新建ActivityCollector类作为活动管理器:
package com.example.myapplication;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
public class ActivityCollector {
public static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for (Activity activity:activities) {
if(! activity.isFinishing()){
activity.finish();
}
}
android.os.Process.killProcess(android.os.Process.myPid());
}
}
每个活动onCreate就addActivity(this),onDestory就removeActivity(this)。 想退出活动就调用finish。
启动活动最佳写法
MainActivity想启动SecondActivity,但不知道传值的键是什么,解决方法: (SecondActivity)
public static void actionStart(Context context,String data1,String data2){
Intent intent = new Intent(context,SecondActivity.class);
intent.putExtra("data1",data1);
intent.putExtra("data2",data2);
context.startActivity(intent);
}
(MainActivity)
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
SecondActivity.actionStart(MainActivity.this,"data1","data2");
}
});
三、UI
最后再详细写吧,想用什么查一下就好了。
控件
TextView
显示文本信息
Button
按钮
EditText
输入和编译内容
ImageView
展示图片
ProgressBar
显示一个进度条,表示程序正在加载一些数据。
AlertDialog
在当前页面弹出一个对话框,这个对话框置顶于所有界面元素之上,能屏蔽掉其他控件的交互能力,可以警告,提示等。
ProgressDialog
在界面上弹出一个对话框,能屏蔽掉其他控件的交互能力,显示一个进度条,表示当前操作比较耗时,请等待。
基本布局
LinearLayout线性布局
RelativeLayout相对布局
FrameLayout帧布局
所有控件默认放在左上角
百分比布局
任意比例分割布局
开源UI框架
Side-Menu.Android 分类侧滑菜单
https://github.com/Yalantis/Side-Menu.Android
AndroidSwipeLayout 滑动Layout
滑动Layout,支持单个View,ListView,GridView。 项目地址: https://github.com/daimajia/AndroidSwipeLayout
未完待续…
|