android项目 之 记事本(13) ----- 查看图片及播放录音

本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020

今天就来实现下查看图片及录音的功能,在编辑或者浏览记事时,点击图片,打开一个自定义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="@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);
			}
		}
	}

至此,就实现了查看图片以及播放录音的功能。

时间: 2024-08-01 18:43:15

android项目 之 记事本(13) ----- 查看图片及播放录音的相关文章

android项目 之 记事本(14) ----- 手势缩放与拖拽图片

本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 上节实现了查看图片及录音的功能,其中查看图片,可以调用系统的图库来查看图片,也可以自定义Activity来查看图片,今天就在上节的基础上,实现手势缩放与拖拽图片. 想必大家都用过系统的图库,浏览图片时,可以通过手势放大或缩小图片,旋转图片,拖拽图片等功能,我们也为自已定义的查看图片的Activity增加手势缩放与拖拽图片的功能,效果如下图: 上面四幅图中,演示了通过手势(多点触

android项目 之 记事本(11) ----- 添加数据库

这节就来为我们的记事本添加数据库支持,这样,就可以在添加记事后将其保存在数据库中,方便下次浏览,修改,删除等. 先看效果图: 三张图片分别演示了保存记事,查看记事,删除记事. 对于数据库而言,无非就是涉及到数据库的创建,增删改查. 为了将数据库的操作封装起来,单独写了一个类,如下: 数据库操作 DatabaseOperation.java [java] view plaincopy import android.content.Context; import android.database.C

android项目 之 记事本(5)----- 添加录音

有时,需要将重要的事以语音的形式记录下来,这个在生活中很常见,今天就为记事本添加录音的功能,先看图: 其实在第一节界面设计中,可以看出记事本的功能选项,其中底部选项栏的第三个就是添加录音.   主要步骤如下:               1.   录音Activity的界面设计.               2.   在语音按钮的监听器中添加Intent,跳转到录音Activity,这里同样是用startActivityforResult(Intent intent,int requestCod

android项目 之 记事本(12) ----- 图片的等比例缩放及给图片添加边框

本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 在Android的UI开发中经常会遇到图片的缩放,就比如记事本,现在的图片都比较大,如果将原图不经缩放直接放在屏幕上,则会占满整个屏幕,而且有时图片会比屏幕还大,这时就不能完全的显示整个图片,所以,必须要进行缩放,但在缩放时,该如何缩放呢,长和宽的缩放比例设置为多少合适呢,为了保持原图的纵横比,所以要最好的方法就是约束缩放比例,也就是等比例缩放,相信大家都用过PS中的缩放图片的

android项目 之 记事本(6)----- 添加手写

想必大家都用过QQ的白板功能,里面主要有两项,一个是涂鸦功能,其实类似于上节的画板功能,而另一个就是手写,那记事本怎么能没有这个功能呢,今天就来为我们的记事本添加手写功能. 先上图,看看效果: 看了效果图,是不是心动了呢?那就赶紧着手做吧,其实,手写功能并不难实现,大体就是全屏书写,定时发送handle消息,更新activity. 实现手写功能的主要步骤: 1. 自定义两个View,一个是TouchView,用于在上面画图,另一个是EditText,用于将手写的字显示在其中,并且,要将两个自定义

android项目 之 记事本(15) ----- 保存手写及绘图

本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 之前,忘了写如何将手写和绘图保存,现在补上. 首先看如何保存绘图,先看效果图: 因为记事本的绘图功能主要用到了画布,而在构建画布时,指定了Bitmap,也就是说在画布上的所画的东西都被保存在了Bitmap中,因此,我们只要保存该Bitmap,就可以将我们的所绘制的图形以图片的形式保存,主要代码如下: /* * 保存所绘图形 * 返回绘图文件的存储路径 * */ public S

android项目 之 记事本(7)----- 手写功能之删除、恢复和清空

上一节,为记事本添加了手写的功能,但是没有实现底部按钮的各种功能,这节就先实现撤销,恢复和清空的功用. 因为不会录制屏幕成gif图片,所以就以图片形式给出吧,不是很形象,凑合着看: 显然,需要为底部GridView的添加item单击事件: private GridView paint_bottomMenu; paint_bottomMenu = (GridView)findViewById(R.id.paintBottomMenu); paint_bottomMenu.setOnItemClic

android项目 之 记事本(9) ----- 画板功能之橡皮擦、画笔大小和画笔颜色

上节已实现了画板中的绘制,删除,恢复入清空的功能,还有橡皮擦,设置画笔大小和画笔颜色没有实现,这节就将这几个功能逐一实现. 先看效果图: 以上图中,第一个展示了设置画笔颜色的功能,第二个展示了设置画笔大小的颜色,而第三个则展示了橡皮擦的功能,细心的可以发现,这节将图标颜色设置为了蓝色,并且,增加了最左边的按钮(其实,就是在gridview中多增加了一个item). 下面分别讨论,橡皮擦,设置画笔大小,设置画笔颜色的主要思想:     1. 橡皮擦功能:                    基本

android项目 之 记事本(8) ----- 画板功能之撤销、恢复和清空

上一节讨论了手写功能中的删除.恢复和清空功能,那么,画板也就是涂鸦怎么能没有撤销.恢复与清空的功能呢,今天就来实现下. 终于会做gif图了,看下面的动态图,是不是和QQ白板功能很像. 之前就简单的只实现了在画板上绘图的功能,所以当时将自定义view直接写在了activity中,这一节由于要实现撤销.恢复及清空的功能,所以将分离出来,单独写成了一个java文件PaintView.java,在该自定义view中实现画板的基本操作. 因为将自定义view单独分离出来,所以需要改到activity的布局