- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
一切正常,但搜索栏在每个 ListView 中更新,但音频正在播放正确的方法
public class AudioPLayAdapter extends BaseAdapter implements
OnCompletionListener, SeekBar.OnSeekBarChangeListener {
private Activity activity;
private ArrayList<String> al_fname = new ArrayList<String>();
private static LayoutInflater inflater = null;
private boolean flag_play;
private MediaPlayer mPlayer = null;
Handler seekHandler = new Handler();
public AudioPLayAdapter(Activity a, ArrayList<String> al_fname) {
activity = a;
mPlayer = new MediaPlayer();
this.al_fname = al_fname;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(final int position, final View convertView,
final ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.audi_rec_lv_layout, null);
final Button play_btn = (Button) vi.findViewById(R.id.play_stop_button);
final SeekBar seekBar = (SeekBar) vi.findViewById(R.id.seekbar_play);
play_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!flag_play) {
play_btn.setText("Stop");
startPlaying();
flag_play = true;
} else {
play_btn.setText("Play");
mPlayer.stop();
seekBar.setProgress(0);
flag_play = false;
}
}
private void startPlaying() {
// TODO Auto-generated method stub
try {
mPlayer.reset();
FileInputStream rawFile = new FileInputStream(al_fname
.get(position));
Log.e("filename", al_fname.get(position));
mPlayer.setDataSource(rawFile.getFD());
// mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
// set Progress bar values
seekBar.setProgress(0);
seekBar.setMax(100);
// seekHandler.postDelayed(updateSeek, 100);
// Updating progress bar
updateProgressBar();
} catch (IOException e) {
Log.e("preparefailed", "prepare() failed");
}
}
private void updateProgressBar() {
// TODO Auto-generated method stub
seekHandler.postDelayed(mUpdateTimeTask, 100);
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
long totalDuration = mPlayer.getDuration();
long currentDuration = mPlayer.getCurrentPosition();
String str1 = new String();
// holder.timer_tv.setText(str1.valueOf(currentDuration));
// Updating progress bar
int progress = (int) (getProgressPercentage(
currentDuration, totalDuration));
// Log.d("Progress", ""+progress);
// if(position==holder.seekBar.getId())
// seekBar.setTag(position);
seekBar.setProgress(progress);
// Running this thread after 100 milliseconds
seekHandler.postDelayed(this, 100);
if (!mPlayer.isPlaying()) {
play_btn.setText("Play");
flag_play = false;
}
if (!flag_play)
seekBar.setProgress(0);
}
private int getProgressPercentage(long currentDuration,
long totalDuration) {
// TODO Auto-generated method stub
Double percentage = (double) 0;
long currentSeconds = (int) (currentDuration / 1000);
long totalSeconds = (int) (totalDuration / 1000);
// calculating percentage
percentage = (((double) currentSeconds) / totalSeconds) * 100;
// return percentage
return percentage.intValue();
}
};
});
return vi;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return al_fname.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
}
}
最佳答案
每次调用 getView
时,都会创建一个新的 OnClickListener
并将其添加到该行 View 的 play_btn
中。
这些匿名 OnClickListener
中的每一个都有一个字段 Runnable mUpdateTimeTask
。这个 runnable 被发布到处理程序,然后它不断地一次又一次地发布自己。
当新行开始播放时,现在有两个 Runnable
发布它们自己并更新可能不同的搜索栏。每次点击播放时,都会添加一个新的额外可运行对象。
您想要的是跟踪正在播放的项目,并在不再需要时停止发布可运行的项目。一次最多应该有 1 个可运行的。甚至可能寻找一种更好的方法来定期更新搜索栏(如果存在)。
在 getView
中,如果 View 被回收(即它来自 convertView
参数),那么您必须检查 View 现在是否用于不同的 位置
,如果是不同的位置,则停止更新该行的seekbar
。
所以你需要这样的东西(仍然缺少一些细节,例如处理歌曲何时结束,或如何停止播放,留作练习):(完整的演示项目位于 https://github.com/curobosqui/PlaybackInList/tree/StackoverfllowAnswer)
public class ListWithSongsActivity extends ListActivity {
private static final int NOT_PLAYING = -1;
private static final String TAG = "SongList";
List<String> mSongs = new ArrayList<String>(50);
private ArrayAdapter<String> mAdapter = null;
private final MediaPlayer mPlayer = new MediaPlayer();
private int mPlayingPosition = NOT_PLAYING;
private Handler mHandler = new Handler();
private PlaybackUpdater mProgressUpdater = new PlaybackUpdater();
public ListWithSongsActivity() {
//add list of songs in your device for sample
mSongs.addAll(Arrays.asList(new String[]{
"/sdcard/Download/B00G2ID7FE_(disc_1)_01_-_Play_Me_(Version).mp3",
"/sdcard/Download/The Slip/10 Demon Seed.mp3"
}));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_list_with_songs);
mAdapter = new ArrayAdapter<String>(this, R.layout.list_item, android.R.id.text1, mSongs) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
ProgressBar pb = (ProgressBar) v.findViewById(R.id.progressBar1); //Cast
if (position == mPlayingPosition) {
//pb.setVisibility(View.VISIBLE);
mProgressUpdater.mBarToUpdate = pb;
mHandler.postDelayed(mProgressUpdater, 100);
} else {
//pb.setVisibility(View.GONE);
pb.setProgress(0);
if (mProgressUpdater.mBarToUpdate == pb) {
//this progress would be updated, but this is the wrong position
mProgressUpdater.mBarToUpdate = null;
}
}
return v;
}
};
setListAdapter(mAdapter);
}
private void stopPlayback()
{
mPlayingPosition = NOT_PLAYING;
mProgressUpdater.mBarToUpdate = null;
mPlayer.stop();
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
//start playing item at position
try {
mPlayer.reset();
mPlayer.setDataSource(mSongs.get(position));
mPlayer.prepare();
mPlayer.start();
mPlayingPosition = position;
mHandler.postDelayed(mProgressUpdater, 500);
//trigger list refresh, this will make progressbar start updating if visible
mAdapter.notifyDataSetChanged();
} catch (IOException e) {
Log.e(TAG, "unable to play: " + mSongs.get(position));
e.printStackTrace();
stopPlayback();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list_with_songs, menu);
return true;
}
@Override
protected void onStop() {
super.onStop();
mPlayer.stop();
}
private class PlaybackUpdater implements Runnable {
public ProgressBar mBarToUpdate = null;
@Override
public void run() {
if ((mPlayingPosition != NOT_PLAYING) && (null != mBarToUpdate)) {
mBarToUpdate.setProgress( (100*mPlayer.getCurrentPosition() / mPlayer.getDuration()) ); //Cast
mHandler.postDelayed(this, 500);
} else {
//not playing so stop updating
}
}
}
}
并使用简单的行布局 list_item.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" >
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
关于android - ListView 中的音频播放器与 Android 中的搜索栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22216500/
我在我的应用程序中使用 Hibernate Search。其中一个子集合被映射为 IndexedEmbedded。子对象有两个字段,一个是 id,另一个是日期(使用日期分辨率到毫秒)。当我搜索 id=
The App Engine Search API有一个 GeoPoint 字段。可以用它来进行半径搜索吗?例如,给定一个 GeoPoint,查找位于特定半径内的所有文档。 截至目前,它看起来像 Ge
客户对我正在做的员工管理项目提出了这个新要求,以允许他们的用户进行自定义 bool 搜索。 基本上允许他们使用:AND、OR、NOT、括号和引号。 实现它的最佳方法是什么?我检查了 mysql,它们使
很想知道哪个更快 - 如果我有一个包含 25000 个键值对的数组和一个包含相同信息的 MySQL 数据库,搜索哪个会更快? 非常感谢大家! 最佳答案 回答这个问题的最好方法是执行基准测试。 关于ph
我喜欢 smartcase,也喜欢 * 和 # 搜索命令。但我更希望 * 和 # 搜索命令区分大小写,而/和 ?搜索命令遵循 smartcase 启发式。 是否有隐藏在某个地方我还没有找到的设置?我宁
我有以下 Marklogic 查询,当在查询控制台中运行时,它允许我检索具有管理员权限的系统用户: xquery version "1.0-ml"; import schema namespace b
我希望当您搜索例如“A”时,所有以“A”开头的全名都会出现。因此,如果名为“Andreas blabla”的用户将显示 我现在有这个: $query = "SELECT full_name, id,
我想在我的网站上添加对人名的搜索。好友列表已经显示在页面上。 我喜欢 Facebook 这样做的方式,您开始输入姓名,Facebook 只会显示与查询匹配的好友。 http://cl.ly/2t2V0
您好,我在我的网站上进行搜索时遇到此错误。 Fatal error: Uncaught Error: Call to undefined function mysql_connect() in /ho
声明( 叠甲 ):鄙人水平有限,本文为作者的学习总结,仅供参考。 1. 搜索介绍 搜索算法包括深度优先搜索(DFS)和广度优先搜索(BFS)这两种,从起点开始,逐渐扩大
我正在为用户列表使用 FuturBuilder。我通过 futur: fetchpost() 通过 API 获取用户。在专栏的开头,我实现了一个搜索栏。那么我该如何实现我的搜索栏正在搜索呢? Cont
我正在使用 MVC5,我想搜索结果并停留在同一页面,这是我在 Controller (LiaisonsProjetsPPController) 中执行搜索操作的方法: public ActionRes
Azure 搜索中的两种方法 Upload 与 MergeOrUpload 之间有什么区别。 他们都做完全相同的事情。即,如果文档不存在,它们都会上传文档;如果文档已经存在,则替换该文档。 由于这两种
实际上,声音匹配/搜索的当前状态是什么?我目前正在远程参与规划一个 Web 应用程序,该应用程序将包含和公开记录的短音频剪辑(最多 3-5 秒,人名)的数据库。已经提出了一个问题,是否可以实现基于用户
在商业应用程序中,具有数百个面并不罕见。当然,并非所有产品都带有所有这些标记。 但是在搜索时,我需要添加一个方面查询字符串参数,其中列出了我想要返回的所有方面。由于我事先不知道相关列表,因此我必须在查
当我使用nvcc 5.0编译.cu文件时,编译器会为我提供以下信息。 /usr/bin/ld: skipping incompatible /usr/local/cuda-5.0/lib/libcud
我正在使用基于丰富的 Lucene 查询解析器语法的 Azure 搜索。我将“~1”定义为距离符号的附加参数)。但我面临的问题是,即使存在完全匹配,实体也没有排序。 (例如,“blue~1”将返回“b
我目前有 3 个类,一个包含 GUI 的主类,我在其中调用此方法,一个包含数据的客户类,以及一个从客户类收集数据并将其放入数组列表的 customerList 类,以及还包含搜索数组列表方法。 我正在
假设我有多个 6 字符的字母数字字符串。 abc123、abc231、abc456、cba123、bac231 和 bac123 。 基本上我想要一个可以搜索和列出所有 abc 实例的选择语句。 我只
我有这个表 "Table"内容: +--------+ | Serial | +--------+ | d100m | <- expected result | D100M | <- expect
我是一名优秀的程序员,十分优秀!