android-从NavigationBar中替换ViewPager中的片段

时间:2015-06-25 21:53:15

标签: android android-fragments android-viewpager android-cardview fragmentmanager

我正在开发一个允许查看曲棍球比赛结果的Android应用程序。 我正在使用带有自定义ViewPager的{​​{1}}来显示三个片段,并使用带有FragmentPagerAdapter的{​​{1}}来显示锦标赛。 当我点击NavigationDrawer个孩子时,我想用所选锦标赛的数据更新这三个片段。

我在ExpandableListView中设置ExpandableListView,我在其中OnchildClickListener并称为NavigationDrawer方法。但它只是返回一个空白屏幕。

我在每个论坛搜索并尝试了不同的解决方案,但没有人有效 当我使用FragmentManager代替replace()并使用ft.add()刷新页面时,我得到了正确的结果,但我想在不手动刷新页面的情况下获取它。 我还尝试将ft.replace()替换为SwipeRefreshLayout,但没有任何改变。

NavigationDrawerFragment

FragmentPagerAdapter

First Fragment

FragmentStatePagerAdapter

编辑:

FragmentPagerAdapter

 package com.dcdeveloper.fihresults;

    public class NavigationDrawerFragment extends Fragment {

    /**
     * Immagazzina lo stato della posizione dell'elemento selezionato.
     */
    private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";

    /**
     * Per the design guidelines, you should show the drawer on launch until the user manually
     * expands it. This shared preference tracks this.
     */
    private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";

    /**
     * A pointer to the current callbacks instance (the Activity).
     */
    private NavigationDrawerCallbacks mCallbacks;

    /**
     * Helper component that ties the action bar to the navigation drawer.
     */
    private ActionBarDrawerToggle mDrawerToggle;
    /**
     * Memorizza l'istanza del DrawerLayout
     */
    private DrawerLayout mDrawerLayout;
    /**View di questa barra di navigazione*/
    private View mFragmentContainerView;
    /**Posizione dell'elemento selezionato all'interno della lista*/
    private int mCurrentSelectedPosition = 0;
    private boolean mFromSavedInstanceState;
    /**Boolean che indica se l'utente è venuto a conoscenza dell'utilizzo della barra laterale.Utilizzato per accessibilità.*/
    private boolean mUserLearnedDrawer;
    private ActionBarDrawerToggle actionBarDrawerToggle;
    /**Lista con elementi espandibili,contiene i dati relativi ai campionati*/
    ExpandableListView expListView;
    /**adapter per inserire i dati nella ExpandableListView*/
    MyExpandableListAdapter expandableListAdapter;
    /*ArrayList dei titoli dei campionati*/
    List<String> listDataHeader;
    /**Hashmap contenente i dati relativi ai campionati,collegati ai relativi titoli*/
    HashMap<String, List<String>> listDataChild;
    HashMap<Campionato,Integer>listaCampionati;
    /**Stringa contenente l'url del WS a cui si effettueranno le richieste HTTP per ricevere i dati dei campionati*/
    String wsURL;
    /**ID del campionato,utilizzato per aggiornare le pagine una volta premuto l'elemento di un campionato nella lista*/
    protected int key;
    /**Memorizza il titolo dell'Activity,in modo da cambiare il titolo della MainActivity*/
    CharSequence mDrawerTitle;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Read in the flag indicating whether or not the user has demonstrated awareness of the
        // drawer. See PREF_USER_LEARNED_DRAWER for details.
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
        mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);

        if (savedInstanceState != null) {
            mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
            mFromSavedInstanceState = true;
        }

        // Select either the default item (0) or the last selected item.
        selectItem(mCurrentSelectedPosition);
        //Stringa contenente l'url del Web Service
        wsURL = "http://fihresults.altervista.org/WebServiceFihResults/service.php";
        //Prepara le intestazioni standard dei campionati
        prepareHeaderData();

    }

    /**
     * Metodo costruttore della view.Utilizza il layout predefinito del frammento.
     * I dati inseriti all'interno del ListLayout vengono ricevuti dal server ed organizzati
     * all' interno della lista.
     *
     */
    @Override
    public View onCreateView(LayoutInflater inflater, final ViewGroup container,
                             Bundle savedInstanceState) {
        expListView  = (ExpandableListView) inflater.inflate(
                R.layout.fragment_navigation_campionati, container, false);
        expListView .setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                selectItem(position);
        mDrawerTitle= getActionBar().getTitle();
            }
        });
        /**
         * Definisce una nuova richiesta HTTP. Essa preleva i nomi ed i dati dei vari campionati,
         * riempiendo degli ArrayList che saranno poi usati per creare l'ExpandableListView
         */
        if(hasConnection(getActivity())) {
            HTTPRequest http=new HTTPRequest() {
            @Override
            protected void onPostExecute(String result) {
                //ArrayList di tutti i children che saranno inseriti nell'ExpandableListView
                ArrayList<String>A1M=new ArrayList();
                ArrayList<String>A1F=new ArrayList();
                ArrayList<String>A2M=new ArrayList();
                ArrayList<String>A2F=new ArrayList();
                ArrayList<String>B=new ArrayList();
                ArrayList<String>U21M=new ArrayList();
                ArrayList<String>U19F=new ArrayList();
                ArrayList<String>U17M=new ArrayList();
                ArrayList<String>U16F=new ArrayList();
                ArrayList<String>U14M=new ArrayList();
                ArrayList<String>U14F=new ArrayList();
                ArrayList<String>U12X=new ArrayList();
                super.onPostExecute(result);
                try {
                    //Formatta il risultato in un JSONArray
                    JSONArray dati = new JSONArray(result);
                    Log.i("INFO",result);
                    String categoria;   //Categoria del campionato
                    String genere;     //Genere (Maschile,Femminile,Misto)
                    String girone;     //Girone del campionato
                    String idcampionato;
                    for(int i=0;i<dati.length();i++)
                    {
                        JSONObject jsonobject = dati.getJSONObject(i);
                        categoria=jsonobject.getString("Categoria");
                        genere= jsonobject.getString("Genere");
                        girone= jsonobject.getString("Girone");
                        idcampionato= jsonobject.getString("IDCampionato");
                        switch (categoria){
                            case "A1":
                                if(genere.equals("Maschile")) {
                                    A1M.add(idcampionato+" Serie " + categoria + " " + genere + " " + girone);
                                }
                                else {
                                    A1F.add(idcampionato+" Serie " + categoria + " " + genere + " " + girone);
                                }
                                break;
                            case "A2":
                                if(genere.equals("Maschile")) {
                                    A2M.add(idcampionato+" Serie " +categoria + " " + genere + " " + girone);
                                }
                                else {
                                    A2F.add(idcampionato+" Serie " +categoria + " " + genere + " " + girone);
                                }
                                break;
                            case "B":
                                B.add(idcampionato+" Serie " +categoria + " " + genere + " "+girone);
                                break;
                            case "UNDER 21":
                                U21M.add(categoria + " " + genere + " "+girone);
                                break;
                            case "UNDER 19":
                                U19F.add(categoria + " " + genere + " "+girone);
                                break;
                            case "UNDER 17":
                                U17M.add(categoria + " " + genere + " "+girone);
                                break;
                            case "UNDER 16":
                                U16F.add(categoria + " " + genere + " "+girone);
                                break;
                            case "UNDER 14":
                                if(genere.equals("Maschile")) {
                                    U14M.add(categoria + " " + genere + " " + girone);
                                }
                                else {
                                    U14F.add(categoria + " " + genere + " " + girone);
                                }
                                break;
                            case "UNDER 12":
                                U12X.add(categoria + " " + genere + " "+girone);
                                break;
                        }
                        setChildGroupData(A1M, A1F, A2M, A2F, B, U21M, U19F, U17M, U16F, U14M
                                , U14F, U12X);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            protected String doInBackground(String... params) {
                return super.doInBackground(params);
            }
        };
        //Effettua richiesta HTTP al WS

            http.execute(wsURL, "0", "mostraCampionati");
            //Crea un adapter per inserire gli ArrayList nell'ExpandableListView
            Log.i("INFO", String.valueOf(listDataChild.size()));
            expandableListAdapter = new MyExpandableListAdapter(getActivity().getBaseContext(), listDataHeader, listDataChild);
            //Sets the adapter for ExpandableList
            expListView.setAdapter(expandableListAdapter);
            //Sets the OnClickListener for childrens of the list
            expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
                @Override
                public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                    String child = (String) parent.getExpandableListAdapter().getChild(groupPosition, childPosition);
                    String[] parti = child.split(" ");
                    key = Integer.parseInt(parti[0]);   //gets the key of tuple which is the first part of the string
                    //gets Fragment Manager
                    FragmentManager fragmentManager = getFragmentManager();
                    //starts the transaction
                    android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction();
                    ft.replace(R.id.viewpager, PagePartite.newInstance(key));   //first page
                    ft.replace(R.id.viewpager, PageClassifica.newInstance(key));    //second page
                    ft.replace(R.id.viewpager, PageStatistiche.newInstance(key));
                    ft.addToBackStack(null);
                    ft.commit();
                    mDrawerTitle = (child);
                    return true;
                }
            });
        }
        else
            Toast.makeText(getActivity(),"Connessione Internet assente",Toast.LENGTH_LONG).show();
        return expListView ;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mCallbacks = (NavigationDrawerCallbacks) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = null;
    }


    /**
     * Per the navigation drawer design guidelines, updates the action bar to show the global app
     * 'context', rather than just what's in the current screen.
     */
    private void showGlobalContextActionBar() {
        ActionBar actionBar = getActionBar();
        actionBar.setDisplayShowTitleEnabled(true);
    }

    private ActionBar getActionBar() {
        return ((ActionBarActivity) getActivity()).getSupportActionBar();
    }


    /**
     * Funzione che riempie l'HashMap ListDataChild con i dati ricevuti tramite richiesta HTTP.
     * @param par   ArrayList contenente i dati per ogni campionato
     */
    protected void setChildGroupData(ArrayList<String> ... par){
        //inserisce i dati dei Children e dei parent in un HashMap
        listDataChild.put(listDataHeader.get(0), par[0]);
        listDataChild.put(listDataHeader.get(1),par[1]);
        listDataChild.put(listDataHeader.get(2),par[2]);
        listDataChild.put(listDataHeader.get(3),par[3]);
        listDataChild.put(listDataHeader.get(4),par[4]);
        listDataChild.put(listDataHeader.get(5),par[5]);
        listDataChild.put(listDataHeader.get(6),par[6]);
        listDataChild.put(listDataHeader.get(7),par[7]);
        listDataChild.put(listDataHeader.get(8),par[8]);
        listDataChild.put(listDataHeader.get(9),par[9]);
        listDataChild.put(listDataHeader.get(10),par[10]);
        listDataChild.put(listDataHeader.get(11),par[11]);
    }

    /**
     * Lista che inserisce i titoli dei campionati all'interno di una HashMap
     */
    private void prepareHeaderData() {
        listDataHeader = new ArrayList<String>();
        listDataChild = new HashMap<String, List<String>>();
        //Titoli delle sezioni
        listDataHeader.add("Serie A1 Maschile");
        listDataHeader.add("Serie A1 Femminile");
        listDataHeader.add("Serie A2 Maschile");
        listDataHeader.add("Serie A2 Femminile");
        listDataHeader.add("Serie B Maschile");
        listDataHeader.add("Under 21 Maschile");
        listDataHeader.add("Under 19 Femminile");
        listDataHeader.add("Under 17 Maschile");
        listDataHeader.add("Under 16 Femminile");
        listDataHeader.add("Under 14 Maschile");
        listDataHeader.add("Under 14 Femminile");
        listDataHeader.add("Under 12 Mista");
    }

    /**
     * Callbacks interface that all activities using this fragment must implement.
     */
    public static interface NavigationDrawerCallbacks {
        /**
         * Called when an item in the navigation drawer is selected.
         */
        void onNavigationDrawerItemSelected(int position);
    }

1 个答案:

答案 0 :(得分:0)

我要向您展示的是通过在每次数据更改时用新实例替换现有片段来更新ViewPager片段的一种非常基本的方法。

这是公式:

  • 允许FragmentPagerAdapter获取更新的数据。在您的情况下,您有一个名为“key”的int值,当用户从导航抽屉中选择一个项目时,该值会更新。我们将在您的FragmentPagerAdapter上设置一个方法,该方法将采用键值参数并开始更新。
  • getItemPosition()上实施FragmentPagerAdapter以返回POSITION_NONE。这将告诉ViewPager当前片段已过期,需要用另一个片段替换。
  • 在适配器的getItem()方法中,在实例化新片段时使用当前键值。 (你已经有了这部分。)

这是我建议的代码更改:

  1. 修改您的Activity,以便您引用FragmentPagerAdapter个实例。

    private MyFragmentPagerAdapter mAdapter;
    
  2. Activity中,确保使用ViewPager设置FragmentPagerAdapter。 (你没有发布你的Activity代码,所以只是确保你没有错过这个。)这可能发生在onCreate()

    mAdapter = new MyFragmentPagerAdapter();
    ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
    
  3. Activity添加方法以接受导航抽屉中的键值并将其传递给适配器(我们将在一分钟内处理适配器):

    public void select(int key) {
        mAdapter.setKey(key);
    }
    
  4. 从导航栏FragmentTransaction中删除此onChildClick()代码:

                //gets Fragment Manager
                FragmentManager fragmentManager = getFragmentManager();
                //starts the transaction
                android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction();
                ft.replace(R.id.viewpager, PagePartite.newInstance(key));   //first page
                ft.replace(R.id.viewpager, PageClassifica.newInstance(key));    //second page
                ft.replace(R.id.viewpager, PageStatistiche.newInstance(key));
                ft.addToBackStack(null);
                ft.commit();
    

    您的MyFragmentPagerAdapter将为您完成所有这些片段管理。所以用以下代码替换该代码:

    ((MainActivity) getActivity()).select(key);
    

    (我不知道您的活动是什么,所以我只使用了MainActivity。)

  5. 覆盖&amp;在getItemPosition()上实施FragmentPagerAdapter,以便始终返回POSITION_NONE

    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
    

    您必须覆盖此方法,因为基类方法只返回POSITION_UNCHANGED,这导致getItem()永远不会被调用。

  6. 最后,添加方法以获取FragmentPagerAdapter上的键值。您已经拥有该键的变量,因此您可以使用它来存储值:

    public void setKey(int key) {
        idcampionato = key;
        notifyDataSetChanged();
    }
    
  7. 所以这是事件的顺序:

    • 用户从导航栏中选择项目。
    • onChildClick()调用Activity.select()值。
    • select()在适配器上调用setKey()
    • 适配器存储键值并调用notifyDataSetChanged()
    • ViewPager通知适配器已更改,并通过调用适配器的getCount()启动,以查看片段数是否已更改。
    • ViewPager在每个页面位置调用getItemPosition()。返回POSITION_NONE,告诉ViewPager该页面上的片段需要删除并替换为新片段。
    • ViewPager然后在每个页面位置调用getItem()。这将调用片段的newInstance方法。由于您的idcampionato值已更新,因此使用新密钥创建片段。
    • ViewPager显示包含更新数据的新片段。

    这不像我最初建议的那样优雅,即只创建一次片段,然后在片段上有一个自定义方法来更新密钥并刷新片段视图。但是这种方法需要更多的代码更改,所以我决定采用更简单的解决方案。