首页 > 代码库 > android项目 之 记事本(13) ----- 查看图片及播放录音
android项目 之 记事本(13) ----- 查看图片及播放录音
今天就来实现下查看图片及录音的功能,在编辑或者浏览记事时,点击图片,打开一个自定义Activity(当然了,也可以调用系统的图库来查看)来查看所添加的图片的原始图片,而不是缩放后的图片,同理,用自定义Activity来查看录音文件,实现播放录音的功能。上图:
从图中也可以看出,我们首先要创建两个Activity,当然了,布局文件也是少不了的,如下:
activity_show_picture.xml
- <?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="match_parent"
- android:orientation="vertical"
- >
- <ImageView
- android:id="@+id/iv_showPic"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="fitCenter"
- />
- </LinearLayout>
ShowPicture.java
- public class ShowPicture extends Activity {
- private ImageView img;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
- setContentView(R.layout.activity_show_picture);
- getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_add);
- //设置标题
- TextView tv_title = (TextView)findViewById(R.id.tv_title);
- tv_title.setText("查看图片");
- Button bt_back = (Button)findViewById(R.id.bt_back);
- bt_back.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- ShowPicture.this.finish();
- }
- });
- Button bt_del = (Button)findViewById(R.id.bt_save);
- bt_del.setBackgroundResource(R.drawable.paint_icon_delete);
- img = (ImageView)findViewById(R.id.iv_showPic);
- Intent intent = this.getIntent();
- String imgPath = intent.getStringExtra("imgPath");
- Bitmap bm = BitmapFactory.decodeFile(imgPath);
- img.setImageBitmap(bm);
- }
- }
主要思想就是用ImageView来显示指定路径的图片,该路径是从前一个Activity中传入进来的。这里的监听事件,只实现了返回的功能,至于,放大缩小图片,旋转图片,下节再实现吧。activity_show_record.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/bg"
- >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center"
- android:layout_centerInParent="true"
- >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:gravity="center"
- android:layout_margin="5dp"
- >
- <ImageView
- android:id="@+id/iv_record_wave_left"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_margin="5dp"
- android:background="@anim/record_wave_left"
- />
- <ImageView
- android:id="@+id/iv_microphone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:src=http://www.mamicode.com/"@drawable/record_microphone_icon"
- android:layout_margin="5dp"
- />
- <ImageView
- android:id="@+id/iv_record_wave_right"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_margin="5dp"
- android:background="@anim/record_wave_right"
- />
- </LinearLayout>
- <TextView
- android:id="@+id/tv_recordTime"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textColor="#499df7"
- android:textSize="20sp"
- android:text="00:00:00"
- android:gravity="center"
- android:layout_margin="5dp"
- />
- </LinearLayout>
- </RelativeLayout>
ShowRecord.java
- public class ShowRecord extends Activity {
- private String audioPath;
- private int isPlaying = 0;
- private AnimationDrawable ad_left,ad_right;
- private Timer mTimer;
- //语音操作对象
- private MediaPlayer mPlayer = null;
- private ImageView iv_record_wave_left,iv_record_wave_right,iv_microphone;
- private TextView tv_recordTime;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
- setContentView(R.layout.activity_show_record);
- getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_add);
- //设置标题
- TextView tv_title = (TextView)findViewById(R.id.tv_title);
- tv_title.setText("查看录音");
- Button bt_back = (Button)findViewById(R.id.bt_back);
- bt_back.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- if(isPlaying == 1){
- mPlayer.stop();
- mPlayer.release();
- }
- ShowRecord.this.finish();
- }
- });
- Button bt_del = (Button)findViewById(R.id.bt_save);
- bt_del.setBackgroundResource(R.drawable.paint_icon_delete);
- Intent intent = this.getIntent();
- audioPath = intent.getStringExtra("audioPath");
- iv_microphone = (ImageView)findViewById(R.id.iv_microphone);
- iv_microphone.setOnClickListener(new ClickEvent());
- iv_record_wave_left = (ImageView)findViewById(R.id.iv_record_wave_left);
- iv_record_wave_right = (ImageView)findViewById(R.id.iv_record_wave_right);
- ad_left = (AnimationDrawable)iv_record_wave_left.getBackground();
- //ad_left = (AnimationDrawable)iv_record_wave_left.getDrawable();
- ad_right = (AnimationDrawable)iv_record_wave_right.getBackground();
- //ad_right = (AnimationDrawable)iv_record_wave_right.getDrawable();
- tv_recordTime = (TextView)findViewById(R.id.tv_recordTime);
- }
- final Handler handler = new Handler(){
- public void handleMessage(Message msg) {
- switch(msg.what){
- case 1 :
- String time[] = tv_recordTime.getText().toString().split(":");
- int hour = Integer.parseInt(time[0]);
- int minute = Integer.parseInt(time[1]);
- int second = Integer.parseInt(time[2]);
- if(second < 59){
- second++;
- }
- else if(second == 59 && minute < 59){
- minute++;
- second = 0;
- }
- if(second == 59 && minute == 59 && hour < 98){
- hour++;
- minute = 0;
- second = 0;
- }
- time[0] = hour + "";
- time[1] = minute + "";
- time[2] = second + "";
- //调整格式显示到屏幕上
- if(second < 10)
- time[2] = "0" + second;
- if(minute < 10)
- time[1] = "0" + minute;
- if(hour < 10)
- time[0] = "0" + hour;
- //显示在TextView中
- tv_recordTime.setText(time[0]+":"+time[1]+":"+time[2]);
- break;
- }
- }
- };
- class ClickEvent implements OnClickListener{
- @Override
- public void onClick(View arg0) {
- // TODO Auto-generated method stub
- //试听
- if(isPlaying == 0){
- isPlaying = 1;
- mPlayer = new MediaPlayer();
- tv_recordTime.setText("00:00:00");
- mTimer = new Timer();
- mPlayer.setOnCompletionListener(new MediaCompletion());
- try {
- mPlayer.setDataSource(audioPath);
- mPlayer.prepare();
- mPlayer.start();
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (SecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalStateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- mTimer.schedule(new TimerTask() {
- @Override
- public void run() {
- Message message = new Message();
- message.what = 1;
- handler.sendMessage(message);
- }
- }, 1000,1000);
- //播放动画
- ad_left.start();
- ad_right.start();
- }
- //结束试听
- else{
- isPlaying = 0;
- mPlayer.stop();
- mPlayer.release();
- mPlayer = null;
- mTimer.cancel();
- mTimer = null;
- //停止动画
- ad_left.stop();
- ad_right.stop();
- }
- }
- }
- class MediaCompletion implements OnCompletionListener{
- @Override
- public void onCompletion(MediaPlayer mp) {
- mTimer.cancel();
- mTimer = null;
- isPlaying = 0;
- //停止动画
- ad_left.stop();
- ad_right.stop();
- Toast.makeText(ShowRecord.this, "播放完毕", Toast.LENGTH_SHORT).show();
- tv_recordTime.setText("00:00:00");
- }
- }
- }
在查看录音时,用到了对播放时间的显示处理,以及动画的播放与停止,稍有点复杂,这些在之前“添加录音”一节就就讲述了。
有了这两个Activity后,那么剩下的工作就是在单击图片或者录音的事件中启动这两个Activity即可。但这就有一个问题,如何在图文混排的EditText中的判断单击的是图片,录音,还是文字呢??这就需要从EditText中的识别那些是图片,那些是文字,再进一步对图片分析到底单击的是那一个图片,从而实现查看具体图片及录音的功能,具体如下:
1. 记录EditText中每个图片的位置及所在源路径
为了实现在编辑和浏览时可以随时查看原图片及录音文件,所以在每次添加图片或录音后,用一个List记住新增加的每个图片或录音的位置及所在路径,当然了,如果是浏览已经存在于数据库中的记事时,在加载数据的同时,同样用ListView来记住所有的图片及录音的位置和路径。主要代码如下:
- //记录editText中的图片,用于单击时判断单击的是那一个图片
- private List<Map<String,String>> imgList = new ArrayList<Map<String,String>>();
每次单击记事列表项,进入查看记事,在加载数据的同时将所有图片及录音的位置及路径记录下来,具体为在loadDate()方法中添加以下代码:
- //用List记录该录音的位置及所在路径,用于单击事件
- Map<String,String> map = new HashMap<String,String>();
- map.put("location", m.start()+"-"+m.end());
- map.put("path", path);
- imgList.add(map);
同理,也要在每次添加图片录音后也要加入相应的代码,在InsertBitmap()函数中添加如下代码:
- //用List记录该录音的位置及所在路径,用于单击事件
- Map<String,String> map = new HashMap<String,String>();
- map.put("location", selectionIndex+"-"+(selectionIndex+spannableString.length()));
- map.put("path", imgPath);
- imgList.add(map);
2. 给EditText添加单击事件
- private LineEditText et_Notes;
- ... ...
- et_Notes.setOnClickListener(new TextClickEvent());
3. 判断单击的是图片还是普通文字
为了判断单击的是图片还是普通文字,用到了Spanned,ImageSpan,主要思想,就是判断当前单击的位置是否在图片的位置范围内,主要代码如下:
- Spanned s = et_Notes.getText();
- ImageSpan[] imageSpans;
- imageSpans = s.getSpans(0, s.length(), ImageSpan.class);
- int selectionStart = et_Notes.getSelectionStart();
- for(ImageSpan span : imageSpans){
- int start = s.getSpanStart(span);
- int end = s.getSpanEnd(span);
- //找到图片
- if(selectionStart >= start && selectionStart < end){
- ... ...
- }
- }
打到了图片,接下来就要判断单击的到底是那一图片呢?
4. 决断单击的具体是那一张图片
这就用到了第一步记录的图片的位置和路径了,显然,就是用位置来判断到底是单击的那一个图片,主要代码如下:
- //查找当前单击的图片是哪一个图片
- //System.out.println(start+"-----------"+end);
- String path = null;
- for(int i = 0;i < imgList.size();i++){
- Map map = imgList.get(i);
- //找到了
- if(map.get("location").equals(start+"-"+end)){
- path = imgList.get(i).get("path");
- break;
- }
- }
5. 判断是录音还是图片,启动对应的Activity,并传递路径
查看图片,有两种方法,一种是调用系统的图库打开图片,另一种就是自定义,这里,我都实现了,打开录音用的是自定义的Activity,如下:
- //接着判断当前图片是否是录音,如果为录音,则跳转到试听录音的Activity,如果不是,则跳转到查看图片的界面
- //录音,则跳转到试听录音的Activity
- if(path.substring(path.length()-3, path.length()).equals("amr")){
- Intent intent = new Intent(AddActivity.this,ShowRecord.class);
- intent.putExtra("audioPath", path);
- startActivity(intent);
- }
- //图片,则跳转到查看图片的界面
- else{
- //有两种方法,查看图片,第一种就是直接调用系统的图库查看图片,第二种是自定义Activity
- //调用系统图库查看图片
- /*Intent intent = new Intent(Intent.ACTION_VIEW);
- File file = new File(path);
- Uri uri = Uri.fromFile(file);
- intent.setDataAndType(uri, "image/*");*/
- //使用自定义Activity
- Intent intent = new Intent(AddActivity.this,ShowPicture.class);
- intent.putExtra("imgPath", path);
- startActivity(intent);
- }
以上,3,4,5步其实都是在单击的监听器中实现的,完整代码如下:
- //为EidtText设置监听器
- class TextClickEvent implements OnClickListener{
- @Override
- public void onClick(View v) {
- Spanned s = et_Notes.getText();
- ImageSpan[] imageSpans;
- imageSpans = s.getSpans(0, s.length(), ImageSpan.class);
- int selectionStart = et_Notes.getSelectionStart();
- for(ImageSpan span : imageSpans){
- int start = s.getSpanStart(span);
- int end = s.getSpanEnd(span);
- //找到图片
- if(selectionStart >= start && selectionStart < end){
- //Bitmap bitmap = ((BitmapDrawable)span.getDrawable()).getBitmap();
- //查找当前单击的图片是哪一个图片
- //System.out.println(start+"-----------"+end);
- String path = null;
- for(int i = 0;i < imgList.size();i++){
- Map map = imgList.get(i);
- //找到了
- if(map.get("location").equals(start+"-"+end)){
- path = imgList.get(i).get("path");
- break;
- }
- }
- //接着判断当前图片是否是录音,如果为录音,则跳转到试听录音的Activity,如果不是,则跳转到查看图片的界面
- //录音,则跳转到试听录音的Activity
- if(path.substring(path.length()-3, path.length()).equals("amr")){
- Intent intent = new Intent(AddActivity.this,ShowRecord.class);
- intent.putExtra("audioPath", path);
- startActivity(intent);
- }
- //图片,则跳转到查看图片的界面
- else{
- //有两种方法,查看图片,第一种就是直接调用系统的图库查看图片,第二种是自定义Activity
- //调用系统图库查看图片
- /*Intent intent = new Intent(Intent.ACTION_VIEW);
- File file = new File(path);
- Uri uri = Uri.fromFile(file);
- intent.setDataAndType(uri, "image/*");*/
- //使用自定义Activity
- Intent intent = new Intent(AddActivity.this,ShowPicture.class);
- intent.putExtra("imgPath", path);
- startActivity(intent);
- }
- }
- else
- //如果单击的是空白出或文字,则获得焦点,即打开软键盘
- imm.showSoftInput(et_Notes, 0);
- }
- }
- }
至此,就实现了查看图片以及播放录音的功能。
android项目 之 记事本(13) ----- 查看图片及播放录音