[英]Fragment loses focus in ViewPager
我正在做音樂播放器。 有兩個活動。 第一個活動是ViewPager
,其中包含四個片段(所有歌曲,播放列表,專輯和歌手)。 其他Activity
用於列出特定播放列表的歌曲。 從ViewPager
的第一片段(即所有歌曲)播放音樂時,一切正常。 現在,當我從第二個片段中打開一個播放列表時,它將打開一個新的Activity
列出該播放列表中的歌曲。 當我單擊播放時,它可以正常播放。 但是,當我返回上一個活動(即ViewPager
)並嘗試播放第一個片段中的歌曲(即所有歌曲)時,它會播放前一個播放列表中的歌曲,該列表來自上一個Activity
。 Fragment
似乎失去了焦點,盡管它可見並且其RecyclerView
單擊不起作用。 它適用於以前的版本,可能是因為其RecyclerView
使用了相同的適配器類。 我不知道我在做什么錯。 請幫忙。
這是我的ViewPager代碼。
public class Home extends AppCompatActivity {
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
Intent service = new Intent(this, MyMusicPlayerService.class);
bindService(service, serviceConnection, Context.BIND_AUTO_CREATE);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new MyMusic();
break;
case 1:
fragment = new PlayList();
break;
case 2:
fragment = new Albums();
break;
case 3:
fragment = new Artist();
break;
}
return fragment;
}
@Override
public int getCount() {
return 4;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getResources().getString(R.string.title1);
case 1:
return getResources().getString(R.string.title2);
case 2:
return getResources().getString(R.string.title3);
case 3:
return getResources().getString(R.string.title4);
}
return null;
}
}
}
所有歌曲片段:我正在編寫ViewPager
的onCreateView()
方法的第一個片段。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_music, container, false);
storage = new Storage(getActivity());
rvAdapter = new RVAdapter(musics, getActivity(), "all");
layoutManager = new LinearLayoutManager(getActivity());
recycler = (RecyclerView) view.findViewById(R.id.recycler);
recycler.setLayoutManager(layoutManager);
rvAdapter.setOnItemClickListener(new RVAdapter.OnRvItemClickListener() {
@Override
public void onRvItemClickListener(ArrayList<String> data, int position) {
storage.storeSongs(musics); //stores all musics of the current list in an Array, in case of next and prev
mListener.onFragmentInteraction(position);
}
});
rvAdapter.setOnOptionClickListener(new RVAdapter.OnOptionClickListener() {
@Override
public void onOptionClick(String mode, ArrayList<String> data) {
processOption(mode, data);
}
});
populate(); // function to populate recyclerview
recycler.setAdapter(rvAdapter);
return view;
}
第二個活動:這是第二個活動的onCreate()
方法,列出從第一個活動的第二個選項卡(播放列表)中打開的特定播放列表的歌曲。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_song);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
LocalBroadcastManager.getInstance(this).registerReceiver(updateReceiver, new IntentFilter(Constants.ACTION.PLAY_INFO));
storage = new Storage(this);
playinfo = (CardView) findViewById(R.id.playinfo);
prev = (ImageView) findViewById(R.id.prev);
playpause = (ImageView) findViewById(R.id.playpause);
fwd = (ImageView) findViewById(R.id.fwd);
title = (TextView) findViewById(R.id.title);
artist = (TextView) findViewById(R.id.artist);
playinfo.setOnClickListener(this);
prev.setOnClickListener(this);
playpause.setOnClickListener(this);
fwd.setOnClickListener(this);
layoutManager = new LinearLayoutManager(this);
recycler = (RecyclerView) findViewById(R.id.recycler);
recycler.setItemAnimator(new DefaultItemAnimator());
recycler.setLayoutManager(layoutManager);
empty = (TextView) findViewById(R.id.empty);
rvAdapter.setOnItemClickListener(new RVAdapter.OnRvItemClickListener() {
@Override
public void onRvItemClickListener(ArrayList<String> data, int position) {
storage.storeSongs(musics); //stores all musics of the current list in an Array, in case of next and prev
Intent intent = new Intent(Constants.ACTION.PLAY_INFO);
intent.putExtra("title", data.get(0));
intent.putExtra("artist", data.get(1));
intent.putExtra("playStatus", "play");
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
storage.storeAudioIndex(position);
Intent intent2 = new Intent(getBaseContext(), MyMusicPlayerService.class);
intent2.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(intent2);//play music
updateBottom();
}
});
rvAdapter.setOnOptionClickListener(new RVAdapter.OnOptionClickListener() {
@Override
public void onOptionClick(String mode, ArrayList<String> data) {
processOption(mode, data);
}
});
recycler.setAdapter(rvAdapter);
}
這太難回答了。 但是,我認為我可以為您提供解決問題的方法的見解,因此,我正在寫一個答案。
據我了解, Home
活動將四個Fragment
托管在ViewPager
。 所有這四個片段都包含RecyclerView
以列出不同的內容。 但是,因此,在這四個Fragment
中的任何一個Fragment
上單擊RecyclerView
中的任何一項, SecondActivity
,其中包含歌曲列表。 據我了解,您可以從兩個不同的地方播放歌曲。 一個是ViewPager
中標記為“ All Songs”的第一個Fragment
,另一個是您在SecondActivity
內部擁有的SecondActivity
中所有其他三個Fragment
的ViewPager
。
現在,我想提出一個設計流程,該流程將幫助您控制正在播放的歌曲。
您需要在Home
活動中托管兩個Fragment
。 一個Fragment
將是ViewPagerContainerFragment
,另一個將是SecondFragment
。 在此處將SecondActivity
轉換為SecondFragment
,並將與ViewPager
相關的代碼從Home
活動移動到ViewPagerContainerFragment
。 默認情況下,在Home
活動的片段容器中設置ViewPagerContainerFragment
。
讓我們在承載這兩個Fragment
的Home
活動中具有一個公共功能。 我只是給您一個示例,請根據您的要求修改功能參數。
public void playSong (List<Music> musics, int position, ArrayList<String> data) {
storage.storeSongs(musics); //stores all musics of the current list in an Array, in case of next and prev
Intent intent = new Intent(Constants.ACTION.PLAY_INFO);
intent.putExtra("title", data.get(0));
intent.putExtra("artist", data.get(1));
intent.putExtra("playStatus", "play");
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
storage.storeAudioIndex(position);
Intent intent2 = new Intent(getBaseContext(), MyMusicPlayerService.class);
intent2.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(intent2); //play music
updateBottom();
}
我不知道您對storage
和data
確切data
,但是這個想法是將必要的參數傳遞給playSong
函數,以播放特定的歌曲並正確處理特定列表中的下一首和上一首歌曲。 如果您可以在playSong
函數中傳遞列表名稱和列表中歌曲的索引,那將是很好的。 這樣我們就可以從一個地方播放這首歌。
現在,您已經在Home
活動中完美地編寫了函數playSong
,該功能可以播放歌曲並維護上一首和下一首歌曲以及該歌曲的播放位置,因此我們的問題已基本解決。 嘗試保持Service
意圖的靜態變量,以免每次不重新初始化MyMusicPlayerService
類。
下一步是從Home
活動中playSong
函數以外的所有地方播放歌曲的代碼。
從AllSongsFragment
修改RecyclerView
上的click操作,如下所示。
rvAdapter.setOnItemClickListener(new RVAdapter.OnRvItemClickListener() {
@Override
public void onRvItemClickListener(ArrayList<String> data, int position) {
((Home) getActivity()).playSong(...); // Call the public function that you have declared in Home activity.
mListener.onFragmentInteraction(position);
}
});
從SecondFragment
調用playSong()
函數的方式與為您播放歌曲的方式相同。
另一種方法
我可以想到另一種方法,而無需將SecondActivity
更改為Fragment
並保留當前結構。 這可以使用LocalBroadcastReceiver
解決。 您可能會考慮在Host
活動中使用BroadcastReceiver
,並且在接收到SecondActivity
和AllSongsFragment
發出的廣播發送后, SecondActivity
在單個位置相應地播放歌曲。 如果您想對BroadcastReceiver
工作原理有一個基本的了解,可以在這里查看我的答案以更好地理解。 這個想法是從單個靜態位置播放和跟蹤歌曲。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.