簡體   English   中英

片段在ViewPager中失去焦點

[英]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;
        }
    }
}

所有歌曲片段:我正在編寫ViewPageronCreateView()方法的第一個片段。

@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中所有其他三個FragmentViewPager

現在,我想提出一個設計流程,該流程將幫助您控制正在播放的歌曲。

您需要在Home活動中托管兩個Fragment 一個Fragment將是ViewPagerContainerFragment ,另一個將是SecondFragment 在此處將SecondActivity轉換為SecondFragment ,並將與ViewPager相關的代碼從Home活動移動到ViewPagerContainerFragment 默認情況下,在Home活動的片段容器中設置ViewPagerContainerFragment

讓我們在承載這兩個FragmentHome活動中具有一個公共功能。 我只是給您一個示例,請根據您的要求修改功能參數。

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();
}

我不知道您對storagedata確切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 ,並且在接收到SecondActivityAllSongsFragment發出的廣播發送后, SecondActivity在單個位置相應地播放歌曲。 如果您想對BroadcastReceiver工作原理有一個基本的了解,可以在這里查看我的答案以更好地理解。 這個想法是從單個靜態位置播放和跟蹤歌曲。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM