在android应用的开发过程中,经常会出现启动一个界面后填写部分内容后带着数据返回启动前的界面,最典型的应用就是登录过程。在很多应用程序的模块中,都有“我的”这个模块,在未登录状态下点击其中的某一项,就会弹出登录界面,登录完成后回到我的界面,会显示一些登录后的数据,这个功能的实现就要用到startActivityForResult.
下面通过一个小demo来说明一下startActivityForResult的使用,以及在实际开发中的一些应用。
demo的效果图如下:
主界面布局:
三个按钮,一个textview
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/btn_a" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dip" android:layout_marginTop="20dip" android:text="启动A界面并返回数据" /> <Button android:id="@+id/btn_b" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dip" android:layout_marginTop="20dip" android:text="启动B界面" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dip" android:orientation="horizontal" > <Button android:id="@+id/btn_login" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录" /> <Button android:id="@+id/btn_logout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" android:text="注销" /> </LinearLayout> <TextView android:id="@+id/tv_content" android:layout_width="match_parent" android:layout_height="30dip" android:layout_marginLeft="20dip" android:layout_marginRight="20dip" android:layout_marginTop="20dip" /> </LinearLayout>
主界面java代码
public void onClick(View v) { Intent intent ; // TODO Auto-generated method stub switch (v.getId()) { case R.id.btn_a: intent = new Intent(MainActivity.this, ActivityA.class); intent.putExtra("data", "传递给A的数据"); startActivityForResult(intent, A); break; case R.id.btn_b: intent = new Intent(MainActivity.this, ActivityB.class); intent.putExtra("data", "传递给B的数据"); startActivity(intent); break; case R.id.btn_login: intent = new Intent(MainActivity.this,LoginActivity.class); intent.putExtra("data", "传递给登录界面的数据"); startActivityForResult(intent, LOGIN); break; case R.id.btn_logout: btnLogin.setClickable(true); logout.setVisibility(View.GONE); btnLogin.setText("登录"); break; default: break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { switch (requestCode) { case A: Bundle bundle = data.getExtras(); String back = bundle.getString("back"); Toast.makeText(getApplicationContext(), "A界面传回来的数据为:::::::"+back, 0).show(); content.setText("A界面传回来的数据"+back); break; case LOGIN: Bundle loginBundle = data.getExtras(); String username = loginBundle.getString("username"); String passwrod = loginBundle.getString("password"); content.setText("登录界面传回来的数据"+username+":::::::"+passwrod); btnLogin.setText("已登录"); btnLogin.setClickable(false); logout.setVisibility(View.VISIBLE); Toast.makeText(getApplicationContext(), username+"::::::::"+passwrod, 0).show(); break; default: break; } } }
其中主要的地方有两个,一个是在启动activity时,如果要带结果返回,则需要使用startActivityForResult(intent, requestcode)这个方法,该方法两个参数一个是带数据的Intent,另一个就是请求码,这个请求码是用于给activity识别是哪个activity返回的数据,因为在一个activity中可能会出现多个startActivityForResult,因此返回的时候,activity为了识别是哪个activity返回的数据就要利用requestcode来进行区分。
上面还有一个很重要的方法onActivityResult(int requestCode, int resultCode, Intent data) 该方法在startActivityForResult启动的activity结束后返回数据时调用,其中第二个参数是结果码,结果码为RESULT_OK时,说明activity顺便结束并返回结果。
第一个参数requestcode就是被启动的activity的识别码,在startActivityForResult方法时传入。
第三个参数data 是Intent型的数据,该数据就是从activity返回回来的数据,可以使用data.getExtras()方法得到bundle,然后从bundle中取出一些基本数据。
通过不同的结果码,对不同的activity返回的数据进行相应的操作,就可以合理的完成一些特定的功能效果。
那么,是不是所有的startActivityForResult启动的activity都回返回数据呢?答案是否定的,要想要activity返回数据,在activity中也要进行响应的一些设置,请看activity的代码
ActivityA的代码如下:
protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); LinearLayout ll = new LinearLayout(this); LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); ll.setLayoutParams(params); ll.setOrientation(LinearLayout.VERTICAL); TextView tv = new TextView(this); tv.setText("我是A界面"); ll.addView(tv); Button close = new Button(this); close.setText("关闭界面并返回"); close.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.putExtra("back", "我是A界面返回的数据"); setResult(RESULT_OK, intent); finish(); } }); ll.addView(close); setContentView(ll); Toast.makeText(getApplicationContext(), getIntent().getExtras().getString("data"), 0).show(); }
注意其中有一段代码,是setResult(RESULT_OK, intent); 之后紧接着 finish();
activity要能成功返回数据,就必须在结束finish()之前调用setResult方法,该方法的两个参数,第一个为结果码,也就是onActivityResult方法中的第二个参数resultcode,一般情况下我们都设置该值为RESULT_OK
ActivityB由于使用的是startActivity 因此无需返回数据
ActivityB的代码如下:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activityb); Button close = (Button) findViewById(R.id.btn_close); close.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub finish(); } }); Toast.makeText(getApplicationContext(), getIntent().getExtras().getString("data"), 0).show(); }
LoginActivity的代码:
protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.login); etUsername = (EditText) findViewById(R.id.et_username); etPassword = (EditText) findViewById(R.id.et_password); Button login = (Button) findViewById(R.id.btn_login); login.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String password = etPassword.getText().toString().trim(); String username = etUsername.getText().toString().trim(); Toast.makeText(getApplicationContext(), "登录成功,返回原来界面", 0) .show(); Intent intent = new Intent(); intent.putExtra("username", username); intent.putExtra("password", password); setResult(RESULT_OK, intent); finish(); } }); Toast.makeText(getApplicationContext(), getIntent().getExtras().getString("data"), 0).show(); }
该界面登录成功后,将用户名和密码返回到主页面,并显示,同时主页面不能再次登录,可以使用注销操作。
到这里,这个小demo就完成了。
主要演示二个功能,一个是启动activity并带结果返回,将结果显示在页面上。
一个是启动activity不带结果返回,这种操作比较常用和简单。
完整的代码:http://download.csdn.net/download/yanglfree/7503139
下面再来说下startActivityForResult另一个比较常用的应用场景:上传头像
效果图如下:
点击头像后,弹出选择对话框,选择相册或者拍照,完成后会出现裁剪界面,裁剪完成后,会将头像显示在界面上,如果有服务器的话,会将头像上传到服务器。
看下几段关键的代码:
头像的点击事件:
public void onClick(View v) { CharSequence[] items = { "查看头像", "手机相册", "手机拍照" }; new AlertDialog.Builder(MainActivity.this).setTitle("上传照片") .setItems(items, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (which == SELECT_PICTURE) { Intent intent = new Intent( Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent, PHOTO_REQUEST_GALLERY); } else if (which == SELECT_CAMERA) { Intent intent = new Intent( "android.media.action.IMAGE_CAPTURE"); // 判断存储卡是否可以用,可用进行存储 if (hasSdcard()) { intent.putExtra( MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File( Environment .getExternalStorageDirectory(), PHOTO_FILE_NAME))); } startActivityForResult(intent, PHOTO_REQUEST_CAMERA); } else if (which == SELECT_SCAN) { // TODO 查看头像 } } }).create().show(); } });
其中,启动相册和拍照都是采用的startAcitivityForResult方法,并且,由于相册和拍照都是系统应用,因此,intent使用指定的intent
拍照: "android.media.action.IMAGE_CAPTURE"
相册:Intent.ACTION_PICK
在activityResult方法中:
public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { if (requestCode == PHOTO_REQUEST_GALLERY) {// 图库 if (data == null) { return; } Uri uri = data.getData(); crop(uri); } else if (requestCode == PHOTO_REQUEST_CAMERA) {// 拍照 if (hasSdcard()) { file = new File(Environment.getExternalStorageDirectory(), PHOTO_FILE_NAME); crop(Uri.fromFile(file)); } else { Toast.makeText(this, "未找到存储卡,无法存储照片!", 0).show(); } } else if (requestCode == PHOTO_REQUEST_CUT) {// 裁剪 try { bmp = data.getParcelableExtra("data"); photo.setImageBitmap(bmp); File tempFile = BitmapUtils.saveBitmapFile(bmp, PHOTO_FILE_NAME); upload(tempFile);//上传到服务器 pd = new ProgressDialog(this); pd.setMessage("头像正在上传中请稍后"); pd.show(); } catch (Exception e) { e.printStackTrace(); } } } }
完整的代码下载:http://download.csdn.net/detail/yanglfree/7504613
Android基础之——startActivityForResult启动界面并返回数据,上传头像