记录使用SeekBar遇到的一些错误
2016-03-07 19:03
791 查看
最近初学Android写一个音乐播放器,用到SeekBar显示歌曲进度遇到的一个坑,记录之。
程序比较简单,用ListView显示歌曲列表,底部用一个SeekBar显示播放进度,两个TextView,一个显示歌曲当前播放位置,一个显示歌曲总时长。
点击列表中的歌曲开始播放歌曲开始播放,拖动SeekBar改变播放进度。运行没什么问题,歌曲也能播放,但是播放一卡一卡的。代码如下:
程序比较简单,用ListView显示歌曲列表,底部用一个SeekBar显示播放进度,两个TextView,一个显示歌曲当前播放位置,一个显示歌曲总时长。
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.androidbasis3_10_4.MainActivity" > <ListView android:id="@+id/main_lv_musiclist" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_alignParentBottom="true" android:gravity="center_horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/main_ll_tv_currentTime" android:textSize="18sp" android:text="00:00"/> <SeekBar android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:progress="0" android:max="100" android:id="@+id/main_ll_sb_playProcess" style="@android:style/Widget.DeviceDefault.SeekBar"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/main_ll_tv_totalTime" android:textSize="18sp" android:text="00:00"/> </LinearLayout> </RelativeLayout>
点击列表中的歌曲开始播放歌曲开始播放,拖动SeekBar改变播放进度。运行没什么问题,歌曲也能播放,但是播放一卡一卡的。代码如下:
public class MainActivity extends Activity implements OnItemClickListener, OnSeekBarChangeListener { private TextView currentTime,totalTime; private SeekBar playProcess; private ListView musicList; private Cursor cursor; private SimpleCursorAdapter adapter; private MediaPlayer player; private boolean flag = true; private Thread thread = null; private Handler mhandler = new Handler(){ public void handleMessage(android.os.Message msg) { if (msg.what == 0x01) { if (flag) { long duration = player.getDuration(); long currentPosition = player.getCurrentPosition(); long position = 100*currentPosition/duration; playProcess.setProgress((int) position); currentTime.setText(parseTime(currentPosition)); } } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); initDatas(); initViewOpr(); } private void initViewOpr() { adapter = new SimpleCursorAdapter(MainActivity.this, R.layout.item_list_main, cursor, new String[]{Media.TITLE}, new int[]{R.id.item_list_musicName}); musicList.setAdapter(adapter); musicList.setOnItemClickListener(this); playProcess.setOnSeekBarChangeListener(this); } private void initDatas() { ContentResolver resolver = getContentResolver(); cursor = resolver.query(Media.EXTERNAL_CONTENT_URI, new String[]{Media._ID,Media.TITLE,Media.DURATION,Media.DATA}, null, null, null); } private void initViews() { currentTime = (TextView) findViewById(R.id.main_ll_tv_currentTime); totalTime = (TextView) findViewById(R.id.main_ll_tv_totalTime); playProcess = (SeekBar) findViewById(R.id.main_ll_sb_playProcess); musicList = (ListView) findViewById(R.id.main_lv_musiclist); player = new MediaPlayer(); } @Override protected void onDestroy() { super.onDestroy(); flag = false; player.release(); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { cursor.moveToPosition(position); long musicTime = cursor.getLong(2); String musicLength = parseTime(musicTime); totalTime.setText(musicLength); player.stop(); player.reset(); try { player.setDataSource(cursor.getString(3)); player.prepare(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } player.start(); if (thread == null) { thread = new Thread(){ @Override public void run() { while (flag) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } mhandler.sendEmptyMessage(0x01); super.run(); } } }; thread.start(); } } private String parseTime(long musicTime) { long min = musicTime/1000/60; long sec = (musicTime/1000)%60; String minStr = ""+min; String secStr = ""+sec; if (min < 10) { minStr = "0" + min; } if (sec < 10) { secStr = "0" + sec; } return minStr+":"+secStr; } /* *通知进度被更改 *参数: *seekBar:当前被修改进度的SeekBar *process:当前进度值。 *fromUser:如果是用户触发的则返回true */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) { long position = player.getDuration()*progress/100; player.seekTo((int)position); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } }找了半天没发现哪里问题,后来仔细查了onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) 这个方法,终于发现了问题的所在,第三个参数fromUser表示如果是用户拖动色SeekBar触发的进度改变的话返回true,之前没有判断fromUser就直接调用player.seekTo()方法了,由于前面在Handler的handleMessage方法中有每隔一秒调用seekbar的setProgress()方法设置进度,也会触发onProgressChanged()方法,形成了一种“递归”的效果,不断的调用player.seekTo()方法,造成了这种一卡一卡的效果。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法