Android基础
- Android基础git地址:https://gitee.com/xiaozhi1998/AndroidBaisi
活动
设置主活动
//在想要设置的活动添加以下代码
基础语法
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);
//获取按钮
Button button1 = (Button) findViewById(R.id.button_1);
//监听点击
button1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
//消息提示
Toast.makeText(FirstActivity.this, "You clicked Button 1", Toast.LENGTH_SHORT).show();
}
});
Button button2 = (Button) findViewById(R.id.button_2);
button2.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
//销毁程序
finish();
}
});
Button button3 = (Button) findViewById(R.id.button_3);
button3.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
//显式Intent
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
}
});
Button button4 = (Button) findViewById(R.id.button_4);
button4.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
//隐式Intent, 只能指定一个action
Intent intent = new Intent("com.example.test02.ACTION_START");
//指定多个category
intent.addCategory("com.example.test02.MY_CATEGORY");
startActivity(intent);
}
});
Button button5 = (Button) findViewById(R.id.button_5);
button5.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(Intent.ACTION_VIEW);
//打开浏览器的百度
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
Button button6 = (Button) findViewById(R.id.button_6);
button6.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(Intent.ACTION_DIAL);
//拨打10086
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//获取菜单
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
//菜单点击监听
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.add_item:
Toast.makeText(FirstActivity.this, "You clicked Add", Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(FirstActivity.this, "You clicked Remove", Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(FirstActivity.this, "You clicked Nothing", Toast.LENGTH_SHORT).show();
}
return true;
}
}
利用元数据传递配置信息
- 在activity节点内部添加meta-data标签
-
Java代码获取元数据信息
- 调用getPackageManager方法获得当前应用的包管理器
- 调用包管理器的getActivityInfo方法获得当前活动的信息对象
- 活动信息对象的metaData是Bundle包裹类型,调用包裹对象的getString即可获得指定名称的参数值
// 显示配置的元数据 private void showMetaData() { try { PackageManager pm = getPackageManager(); // 获取应用包管理器 // 从应用包管理器中获取当前的活动信息 ActivityInfo act = pm.getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); Bundle bundle = act.metaData; // 获取活动附加的元数据信息 String value = bundle.getString("weather"); // 从包裹中取出名叫weather的字符串 tv_meta.setText("来自元数据信息:今天的天气是"+value); // 在文本视图上显示文字 } catch (Exception e) { e.printStackTrace(); } }
传递数据
Intent
-
Intent用于Android各组件之间的通信,主要完成下列3部分工作
- 标记本次从哪里来、到哪里去、要怎么走
- 发起方携带本次通信需要的数据内容,接收方从收到的意图中解析数据
- 发起方若想判断接收方的处理结果,意图就要负责让接收方传回应答的数据内容
-
七大属性
-
Component,setComponent,组件,指定意图的来源于目标
-
Action,setAction,动作,它指定意图的动作行为
- ACTION_MAIN:App启动时的入口
- ACTION_VIEW:向永固红显示数据
- ACTION_SEND:分享内容
- ACTION_CALL:直接拨号
- ACTION_DIAL:准备拨号
- ACTION_SENDTO:发送短信
- ACTION_ANSWER:接听电话
-
Data,setData,即Uri,指定动作要操作的数据路径,八大类型(Int、Double、Float、Boolean、String、StringArray、StringArrayList、Serializable)
-
Category,addCategory,类别,指定意图的操作类型
-
Type,setType,数据类型,指定消息的数据类型
-
Extras,putExtras,扩展信息,指定装载的包裹信息
-
Flags,setFlags,标志位,指定活动的启动标志
-
-
指定意图对象的目标有两种表达方式:显式Intent和隐式Intent
- 显式Intent,直接指定来源活动和目标活动,属于精确匹配
- 隐式Intent,没有给出明确要跳转的目标活动,只给出一个动作字符串让系统自动匹配,属于模糊匹配
//A
public void onClick(View v){
//数据传输
String data = "Hello, xiaozhi";
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("extra_data", data);
startActivity(intent);
}
//B
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Toast.makeText(SecondActivity.this, data, Toast.LENGTH_SHORT).show();
Bundle
//A
public void toSecond(View view) {
Intent intent = new Intent(this, Main2Activity.class);
Bundle bundle = new Bundle();
bundle.putString("name", "xiaozhi");
bundle.putInt("age", 24);
intent.putExtras(bundle);
startActivity(intent);
}
//B
Intent intent = getIntent();
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age", 0);
Toast.makeText(this, "name:" + name + "age:" + age, Toast.LENGTH_SHORT).show();
返回上一层时带数据
//重新启动时可以获取数据 A
Button button8 = (Button) findViewById(R.id.button_8);
button8.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(FirstActivity.this, ThirdActivity.class);
startActivityForResult(intent, 1);
}
});
//设置返回数据 B
public void onClick(View v){
Intent intent = new Intent();
intent.putExtra("data_return", "xiaozhi, hi");
setResult(RESULT_OK, intent);
finish();
}
//获取上一个活动返回的数据 A
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case 1:
if(resultCode == RESULT_OK){
String returnData = data.getStringExtra("data_return");
Toast.makeText(FirstActivity.this, returnData, Toast.LENGTH_SHORT).show();
}
}
}
生命周期
- 运行状态:位于栈顶
- 暂停状态:仍然可见,但不是位于栈顶
- 停止活动:不位于栈顶,也不可见
- 摧毁活动:从返回栈移除,系统回收内存
生存期
- 七个回调方法
- onCreate():活动第一次创建的时候
- onStart():活动由不可见变为可见时
- onResume():活动位于栈顶,处于运行状态,准备和用户交互时
- onPause():系统准备去启动或恢复另一个活动时
- onStop():活动完全不可见时时
- onDestroy():活动在被摧毁之前调用
- onRestart():活动由停止状态变为运行状态之前调用
- 完整生存期:onCreate()到onDestroy(),在onDestroy()中完成释放内存
- 可见生存期:onStart()到onStop(),活动对用户总是可见,onStart()中加载资源,onStop()释放资源
- 前台生存期:onResume()到onPause(),活动总是处于运行状态
- 活动回收A启动B,系统内存不足回收A,按返回键还是会返回A,但是执行的是onRestart,但是如果有数据可能会被丢失,可以重写onSaveInstanceState来保存数据
//保存数据
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onPostCreate(outState);
String tempDate = "hi,xiaozhi";
outState.putString("data_key", tempDate);
}
//恢复数据,onCreate()中
if(savedInstanceState != null){
String tempData = savedInstanceState.getString("data_key");
Toast.makeText(FirstActivity.this, tempData, Toast.LENGTH_SHORT).show();
}
启动模式
可以使用android:launchMode来指定模式
- standard:默认启动模式,每次启动都会创建一个新的实例,并处于栈顶
- singleTop:如果栈顶是该活动,则不会再创建新的实例
- singleTask:如果返回栈存在该活动,则不会再创建新的实例
- singleInstance:启动一个新的返回栈创建实例,getTaskId()可以获取当前栈的id。活动A、C为标准启动,B为singleInstance启动,A启动B,B启动C,按下back,会直接返回A
知晓活动
新建类BaseActivity继承AppCompatActivity,重写onCreate,再让其他活动基础BaseActivity
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity", getClass().getSimpleName());
}
}
一键退出程序
- 新建一个类作为活动管理器
public class ActivityCollector {
public static List 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){
activity.finish();
}
//杀掉当前进程
android.os.Process.killProcess(android.os.Process.myPid());
}
}
- 在BaseActivity类中重写onCreate和onDestroy()
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity", getClass().getSimpleName());
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
- 在按钮点击事件调用ActivityCollector.finishAll()即可一键退出
- 可以在摧毁所有活动后再加上杀掉当前进程的代码
启动活动的最佳写法
- 当启动SecondActivity必须传入两个重要的参数时
//在SecondActivity添加actionStart方法
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);
}
- 方便查看所需参数,调用actionStart即可
SecondActivity.actionStart(FirstActivity.this,"data1","data2");
常用控件
公共属性
- layout_width:宽度,layout_height:高度
- match_parent:和父控件相同
- wrap_content:刚好包含住里面的内容
- visibility:是否可见,可以使用setVisibility()动态修改值
- visible:默认值,可见
- invisible:不可见,但是占用空间
- gone:不可见也不占用空间
- background:背景
- layout_margin:偏移
TextView
-
textStyle:字体风格,normal(无效果)、italic(斜体)、bold(加粗)
-
gravity:文字对齐方式
-
textColor:字体颜色
-
textSize:字体大小,单位sp(可随系统设置变换),还有dp(只和屏幕尺寸相关)和px(越大越清晰)
-
带阴影的TextView
- shadowColor:设置阴影的颜色,要与shadowRadius一起使用
- shadowRadius:设置阴影的模糊程度,设置为0.1就变成字体颜色了,建议使用3.0
- shadowDx、shadowDy:阴影在水平、竖直方法的偏移
-
滚动文本
- singleLine:内容单行显示
- ellipsize:在哪里省略文本
- start:省略号显示在开头
- end:省略号显示在结尾
- middle:省略号显示在中间
- marquee:以横向滚动方式显示(需获得当前焦点时)
- focusable:是否可以获取焦点
- focusableInTouchMode:用于控制视图在触摸模式下是否可以聚焦
- marqueeRepeatLimit:字幕动画重复的次数
- -1、marquee_forever:无限次
- 1:一次
- requestFocus:请求焦点
按钮
-
Button和ImageButton的差异
- Button即可以显示文本也可以显示图片,ImageButton只能显示图片,为避免显示不全scaleType必须为fitCenter
- ImageButton上的图像可按比例缩放,Button通过设置背景的图像会被拉伸变形(fitXY)
- Button只能靠背景显示一张图片,而ImageButton可分别在前景和背景显示图片,从而实现两张图片叠加的效果
-
textAllCaps:false为禁用自动大写转换
-
drawableTop:指定文字上方的图片,除此之外还有drawableBottom、drawableLeft、drawableRight
-
drawablePadding:指定图片与文字的距离
-
enabled:false为禁用
-
selector
- state_pressed:按下
-
点击事件、长按事件、触摸事件
//点击事件 btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e(TAG, "onClick: "); } }); //长按事件 btn.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { Log.e(TAG, "onLongClick: "); //如果返回true,则表示消费点击事件 return false; } }); //触摸事件 btn.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Log.e(TAG, "onTouch: " + event.getAction()); //如果返回true,则表示消费点击事件 return false; } }); // 输出 // E/xiaozhi: onTouch: 0 // E/xiaozhi: onTouch: 2 // E/xiaozhi: onTouch: 2 // E/xiaozhi: onLongClick: // E/xiaozhi: onTouch: 1 // E/xiaozhi: onClick: -
注册监听器
- 匿名类
- 实现接口
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button)findViewById(R.id.bottom); button.setOnClickListener(this); } //点击 @Override public void onClick(View v) { switch (v.getId()){ case R.id.button: //在此处添加逻辑 break; default: break; } } //长按超过500ms @Override public boolean onLongClick(View v) { if (v.getId() == R.id.button) { //在此处添加逻辑 } return true; } }
文本输入框
- hint:输入框提示
- textColorHint:提示字体的颜色
- inputType:输入类型
- numberDecimal:可以带小数点的浮点格式
- number:0-9
- textPassword:输入的字符会变成星号
- maxLines:输入框最大行数
- maxLength:输入框最大字符数
- 获取输入框内容
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.bottom);
editText = (EditText)findViewById(R.id.edit_text);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button:
String inputText = editText.getText().toString();
Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
}
图片
-
src:图片地址
-
maxWidth:最大宽度
-
maxHeight:最大高度
-
adjustViewBounds:调整View的界限,配合maxWidth、maxHeight实现最大限度的等比缩放
-
scaleType:以FIT_开头的4种,它们的共同点都会对图片进行缩放,以CENTER_开头的3种,它们的共同点是居中显示,图片的中心点会与ImageView的中心点重
- FIT_CENTER,默认,图片会被等比缩放到能够填充控件大小,并居中展示
- FIT_START,图片等比缩放到控件大小,并放置在控件的上边或左边展示,多余的上/右半部份留白
- FIT_END,图片等比缩放到控件大小,并放置在控件的下边或右边展示,多余的下/右半部份留白
- FIT_XY,图片缩放到控件大小,完全填充控件大小展示,非等比缩放
- CENTER,不使用缩放,如果图片的大小小于控件的宽高,那么图片会被居中显示,只显示控件尺寸
- CENTER_CROP,图片会被等比缩放直到完全填充整个ImageView,裁剪后并居中显示
- CENTER_INSIDE,图片将被等比缩放到能够完整展示在ImageView中并居中,如果图片大小小于控件大小,那么就直接居中展示该图片
- MATRIX,该模式需要与ImageView.setImageMatrix(Matrix matrix) 配合使用
imageView.setScaleType(ImageView.ScaleType.MATRIX); //设置为矩阵模式 Matrix matrix = new Matrix(); //创建一个单位矩阵 matrix.setTranslate(100, 100); //平移x和y各100单位 matrix.preRotate(30); //顺时针旋转30度 imageView.setImageMatrix(matrix); //设置并应用矩阵 -
动态修改图片地址
public class MainActivity extends BaseActivity implements View.OnClickListener {
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1 = (Button)findViewById(R.id.button_1);
imageView = (ImageView)findViewById(R.id.image_view);
button1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button_1:
imageView.setImageResource(R.drawable.b);
break;
default:
break;
}
}
}
进度条
- 默认为圆形转圈动画
- progressBarStyleHorizontal:条形进度条
- max:进度条最大值,可以动态修改进度条进度
- indeterminate:设置为true可隐藏进度值
int progress = progressBar.getProgress();
progress = progress +10;
progressBar.setProgress(progress);
通知
- Notification与NotificationManager
- NotificationManager类是一个通知管理器类,这个对象是由对象维护的服务,是以单例模式的方式获得,所以一般并不直接实例化这个对象。在Activity中,可以使用Activity.getSystemService(Context.NOTIFICATION_SERVICE)方法获取NotificationManager对象,Activity.getSystemService(String)方法可以通过Android系统级服务的句柄,返回对应的对象。
- 使用NotificationCompat类的Builder构造器来创建Notification对象,可以保证程序在所有的版本上都能正常工作。Android 8.0新增了通知渠道这个概念,如果没有设置,则通知无法在Android 8.0的机器上显示。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "xiaozhi";
private NotificationManager manager;
private Notification notification;
private PendingIntent pendingIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("xiaozhi", "聊天消息", NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
}
Intent intent = new Intent(this, Main2Activity.class);
pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
}
public void sentNotification(View view) {
if (!NotificationManagerCompat.from(this).areNotificationsEnabled()) {
//未打开通知
AlertDialog alertDialog = new AlertDialog.Builder(this)
.setTitle("提示")
.setMessage("请在“通知”中打开通知权限")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
})
.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("android.provider.extra.APP_PACKAGE", MainActivity.this.getPackageName());
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.0
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("app_package", MainActivity.this.getPackageName());
intent.putExtra("app_uid", MainActivity.this.getApplicationInfo().uid);
startActivity(intent);
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) { //4.4
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + MainActivity.this.getPackageName()));
} else if (Build.VERSION.SDK_INT >= 15) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", MainActivity.this.getPackageName(), null));
}
startActivity(intent);
}
})
.create();
alertDialog.show();
alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(Color.BLACK);
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.BLACK);
}
notification = new NotificationCompat.Builder(this, "xiaozhi")
.setContentTitle("官方通知")
.setContentText("小志,你好")
.setSmallIcon(R.drawable.ic_account_circle_black_24dp)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.p1))
.setColor(Color.parseColor("#ff0000"))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
manager.notify(1, notification);
}
//取消通知
public void cancelNotification(View view) {
manager.cancel(1);
}
}
导航栏
- 自定义导航栏:修改style.xml样式