我正在开发一个允许查看曲棍球比赛结果的Android应用程序。
我正在使用带有自定义ViewPager
的{{1}}来显示三个片段,并使用带有FragmentPagerAdapter
的{{1}}来显示锦标赛。
当我点击NavigationDrawer
个孩子时,我想用所选锦标赛的数据更新这三个片段。
我在ExpandableListView
中设置ExpandableListView
,我在其中OnchildClickListener
并称为NavigationDrawer
方法。但它只是返回一个空白屏幕。
我在每个论坛搜索并尝试了不同的解决方案,但没有人有效
当我使用FragmentManager
代替replace()
并使用ft.add()
刷新页面时,我得到了正确的结果,但我想在不手动刷新页面的情况下获取它。
我还尝试将ft.replace()
替换为SwipeRefreshLayout
,但没有任何改变。
FragmentPagerAdapter
FragmentStatePagerAdapter
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);
}
答案 0 :(得分:0)
我要向您展示的是通过在每次数据更改时用新实例替换现有片段来更新ViewPager
片段的一种非常基本的方法。
这是公式:
FragmentPagerAdapter
获取更新的数据。在您的情况下,您有一个名为“key”的int值,当用户从导航抽屉中选择一个项目时,该值会更新。我们将在您的FragmentPagerAdapter
上设置一个方法,该方法将采用键值参数并开始更新。getItemPosition()
上实施FragmentPagerAdapter
以返回POSITION_NONE
。这将告诉ViewPager
当前片段已过期,需要用另一个片段替换。getItem()
方法中,在实例化新片段时使用当前键值。 (你已经有了这部分。)这是我建议的代码更改:
修改您的Activity
,以便您引用FragmentPagerAdapter
个实例。
private MyFragmentPagerAdapter mAdapter;
在Activity
中,确保使用ViewPager
设置FragmentPagerAdapter
。 (你没有发布你的Activity
代码,所以只是确保你没有错过这个。)这可能发生在onCreate()
。
mAdapter = new MyFragmentPagerAdapter();
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
向Activity
添加方法以接受导航抽屉中的键值并将其传递给适配器(我们将在一分钟内处理适配器):
public void select(int key) {
mAdapter.setKey(key);
}
从导航栏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
。)
覆盖&amp;在getItemPosition()
上实施FragmentPagerAdapter
,以便始终返回POSITION_NONE
:
public int getItemPosition(Object object) {
return POSITION_NONE;
}
您必须覆盖此方法,因为基类方法只返回POSITION_UNCHANGED
,这导致getItem()
永远不会被调用。
最后,添加方法以获取FragmentPagerAdapter
上的键值。您已经拥有该键的变量,因此您可以使用它来存储值:
public void setKey(int key) {
idcampionato = key;
notifyDataSetChanged();
}
所以这是事件的顺序:
onChildClick()
调用Activity.select()
值。select()
在适配器上调用setKey()
。notifyDataSetChanged()
。ViewPager
通知适配器已更改,并通过调用适配器的getCount()
启动,以查看片段数是否已更改。ViewPager
在每个页面位置调用getItemPosition()
。返回POSITION_NONE
,告诉ViewPager
该页面上的片段需要删除并替换为新片段。ViewPager
然后在每个页面位置调用getItem()
。这将调用片段的newInstance
方法。由于您的idcampionato
值已更新,因此使用新密钥创建片段。ViewPager
显示包含更新数据的新片段。这不像我最初建议的那样优雅,即只创建一次片段,然后在片段上有一个自定义方法来更新密钥并刷新片段视图。但是这种方法需要更多的代码更改,所以我决定采用更简单的解决方案。