1.Activity
文档
活动代表了一个具有用户界面的单一屏幕, 如 Java 的窗口或者帧.Android 的活动是 ContextThemeWrapper 类的子类.
如果你曾经用 C,C++ 或者 Java 语言编程, 你应该知道这些程序从 main() 函数开始.很类似的, Android 系统初始化它的程序是通过活动中的 onCreate() 回调的调用开始的.存在有一序列的回调方法来启动一个活动, 同时有一序列的方法来关闭活动,
Activity 是与用户交互的入口点.它表示拥有界面的单个屏幕.例如, 电子邮件应用可能有一个显示新电子邮件列表的 Activity 一个用于撰写电子邮件的 Activity 以及一个用于阅读电子邮件的 Activity.
尽管这些 Activity 通过协作在电子邮件应用中形成一种紧密结合的用户体验, 但每个 Activity 都独立于其他 Activity 而存在.因此, 其他应用可以启动其中任何一个 Activity (如果电子邮件应用允许) . 例如, 相机应用可以启动电子邮件应用内用于撰写新电子邮件的 Activity, 以便用户共享图片.
注册
AndroidManifest.xml 注册
<activity
android:name=".MainActivity"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="FROM_BOOT" />
<!-- 意图过滤 , 从LAUNCHER启动 必须!-->
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>- 声明 intent 过滤器 Intent 过滤器是 Android 平台的一项非常强大的功能.借助这项功能, 您不但可以根据显式请求启动 Activity, 还可以根据隐式请求启动 Activity.
例如, 显式请求可能会告诉系统”在 Gmail 应用中启动‘发送电子邮件’Activity”, 而隐式请求可能会告诉系统”在任何能够完成此工作的 Activity 中启动‘发送电子邮件’屏幕”.当系统界面询问用户使用哪个应用来执行任务时, 这就是 intent 过滤器在起作用.
代码
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final String FROM_BOOT = "FROM_BOOT";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UncaughtHandler.getInstance().init(this);
//在锁屏 界面 显示
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
// | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
setContentView(R.layout.activity_main);
//start
final Intent intent = new Intent(this, LinstenService.class);
startService(intent);
//scan
Button but_scan = (Button) findViewById(R.id.but_scan);
but_scan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
IntentIntegrator integrator = new IntentIntegrator(MainActivity.this);
// 设置要扫描的条码类型, ONE_D_CODE_TYPES: 一维码, QR_CODE_TYPES-二维码
integrator.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES);
integrator.setCaptureActivity(ScanActivity.class);
integrator.setPrompt("请扫描条形码"); //底部的提示文字, 设为""可以置空
integrator.setCameraId(0); //前置或者后置摄像头
integrator.setBeepEnabled(true); //扫描成功的「哔哔」声, 默认开启
integrator.setBarcodeImageEnabled(true);
integrator.initiateScan();
}
});
}
@Override
protected void onStart() {
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
// String result = scanResult.getContents();
// Toast.makeText(this, "TTT result="+result, Toast.LENGTH_SHORT).show();
/*
if (result != null) {
Intent it2 = new Intent(this, SampleViewActivity.class);
//Toast.makeText(this, "result="+result, Toast.LENGTH_SHORT).show();
Log.i(TAG, "scan result = "+result);
it2.putExtra("barCode", result);
startActivity(it2);
}*/
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}回调 描述 onCreate() 这是第一个回调, 在活动第一次创建时调用 onStart() 这个回调在活动为用户可见时被调用 onResume() 这个回调在应用程序与用户开始可交互的时候调用 onPause() 被暂停的活动无法接受用户输入, 不能执行任何代码.当前活动将要被暂停, 上一个活动将要被恢复时调用 onStop() 当活动不在可见时调用 onDestroy() 当活动被系统销毁之前调用 onRestart() 当活动被停止以后重新打开时调用
Activity 的交互
一个交互 例子
- 传递参数 启动
Intent confIntent = new Intent(this, ConfigActivity.class);
confIntent.putExtra("id","123");
startActivity(confIntent);- 另外一边 接受
String id = this.getIntent().getStringExtra("id");
- 通过一个意图对象(Intent)
Intent.putExtra(key,val)传参startActivity(confIntent)启动 Activity (亦可以启动其他组件, 例如服务startService(intent);), - Activity 结束后通过
setResult(int resultCode, Intent data)返回结果, - 上一个Activity结束后, 通过
onActivityResult(int requestCode, int resultCode, Intent data)得到结果
使用 Bundle 绑定参数
如果是要从A界面传到B界面, B界面要再传到C界面, Intent就要写两遍添加值的方法 那么 如果我用1个Bundle 直接把值先存里边 然后再存到Intent中 不就更简洁吗?
//传递参数 启动
Intent intent = new Intent(this, ConfigActivity.class);
Bundle bundle = new Bundle();
bundle.putString("key1", value1);
bundle.putString("key2", value2);
intent.putExtras(bundle);
startActivity(bundle);
///////////////////////////////////////////
Intent resultIntent = new Intent();
resultIntent.putExtra("key", "value"); // 设置需要返回的数据,可根据需要添加数据
// 将数据设置到结果Intent中,并指定结果码(RESULT_OK通常表示操作成功)
setResult(Activity.RESULT_OK, resultIntent);
// 结束当前Activity并返回结果Intent
finish();//另外一边 接受
Bundle bundle = this.getIntent().getExtras();
String v = bundle.getString("key1");一个调用系统拍照Activity的例子
//启动
Intent intentCamer = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// MediaStore.ACTION_IMAGE_CAPTURE 系统拍照Activity 常量
String filePath = "/sdcard/" + System.currentTimeMillis() + ".jpg";//要保存照片的绝对路径
try {
ContentValues contentValues = new ContentValues(2);
contentValues.put(MediaStore.Images.Media.DATA, filePath);
//如果想拍完存在系统相机的默认目录,改为
//contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "111111.jpg");
contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
Uri mPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
intentCamer.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri);
startActivityForResult(intentCamer,0);
}catch(SecurityException e){
Toast.makeText(MainActivity.this, "没有权限,访问相机.", Toast.LENGTH_LONG).show();
}
//接受结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Bitmap bitmap= null;
if (data!= null && data.getData() == null) {
//获取到的是Thumbnail所以会很小.但是你传了output路径进去, output路径在拍完照会被写入图片数据
bitmap = (Bitmap) data.getExtras().get("data");
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap( bitmap);
Log.i(TAG, "height="+ bitmap.getHeight()+", width="+ bitmap.getWidth());
}
}
需要 访问相机 和 读写文件权限
新API
在Android SDK 23中,startActivityForResult和onActivityResult,已经被官方标记为弃用了,继而推出了名为Activity Result API的组件。
ActivityResultLauncher<Intent> activityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
// 处理返回的数据
Intent data = result.getData();
// 可以在这里处理返回的Intent中的数据
}
}
);
// 启动目标Activity并处理返回结果
Intent intent = new Intent(this, YourSecondActivity.class);
activityLauncher.launch(intent);自定义组件
- xml布局指定类名
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="@+id/dbv_custom"
android:layout_width="match_parent"
android:layout_height="150dp"
app:zxing_preview_scaling_strategy="fitXY" />
- 然后继承 安卓组件, 它会回调事件以及方法
注意要重写几个有参构造
class DecoratedBarcodeView extends FrameLayout{
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
}
}获取xml的属性
public MyImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
//第一个参数命名空间,
/*取得资源ID号,第一个参数:命名空间名.第二个参数:xml文件里设置的属性名.第三个参数:默认值*/
final String xmlns="http://schemas.android.com/apk/res/android";
int resouceId = attrs.getAttributeResourceValue(xmlns, "text", -1);
if(resouceId > 0)
text = context.getResources().getText( resouceId).toString();//xml里 要通过引用的方式 @string/xxx
}
一个手写面板的自定义控件实现
- 使用
<com.joinken.group.activity.HandWritePanel
android:id="@+id/hwp"
android:layout_width="wrap_content"
android:layout_height="250dp"
android:background="@drawable/sign_bg" />
HandWritePanel hwp
//找到 实例
hwp = (HandWritePanel) findViewById(R.id.hwp);
/**
* 保存图片到SD卡上
*/
protected boolean saveBitmap(String fileName) {
boolean ret = false;
FileOutputStream stream = null;
Bitmap baseBitmap = hwp.getPic();
try {
// 保存图片到SD卡上
File file = new File(fileName);
stream = new FileOutputStream(file);
baseBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
// Toast.makeText(SignActivity.this, "保存成功", Toast.LENGTH_LONG).show();
ret = true;
} catch (Exception e) {
Toast.makeText(SignActivity.this, "保存失败!"+e.getMessage(), Toast.LENGTH_LONG).show();
}finally{
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return ret;
}
//清除
hwp.clean();Activity 多xml布局 查找控件
LayoutInflater layout=this.getLayoutInflater();
View view=layout.inflate(R.layout.layout_sample_view, null);//代码新建布局
setContentView(view);//在设置完布局后
//指定在这个view 中查找
EditText editText = view.findViewById(R.id.id_);
editText.setText(bean.getId());