2017-04-14 85 views
0

我想製作一個測驗應用程序。到目前爲止,我有3個活動 - 家庭,測驗,得分。由於測驗活動包含多個等效的視圖(圖片標題,問題和4個答案按鈕),我做了一些閱讀,並決定 ViewPagerFragmentStatePagerAdapter顯示做伎倆。因此,我製作了一個xml模板,並誇大了幾個測試視圖,並且這一切都看起來不錯,直到我開始處理用戶交互。如何在Android中正確使用ViewPager

我想模擬切換按鈕,每個問題只有一個正確的答案,所以選擇一個按鈕應該取消選擇前一個(如果有的話)。當按下按鈕時,我改變我的Question model,然後我找到所有4個按鈕,並且重置他們的濾色器。然後我將該過濾器重新放回到我選定的按鈕上。要確定要更新哪個問題模型,我使用我在模板根視圖中設置的當前位置fragment(在片段的onCreate中使用setTag)。

這是我打電話給我的fragmets:

public Fragment getItem(int position) { 
    Question question = Repository.findById(position); 
    int correctAnswerBtnId; 
    switch (question.getCorrectAnswerIndex()) { 
     case 0: correctAnswerBtnId = R.id.quiz_answer_0_btn; break; 
     case 1: correctAnswerBtnId = R.id.quiz_answer_1_btn; break; 
     case 2: correctAnswerBtnId = R.id.quiz_answer_2_btn; break; 
     case 3: correctAnswerBtnId = R.id.quiz_answer_3_btn; break; 
    this.ACTIVITY_ROOT.setTag(question.getID()); 

    Fragment fragment = new QuestionFragment(); 
    Bundle args = new Bundle(); 
    args.putSerializable(QuestionFragment.QUESTION, question); 
    fragment.setArguments(args); 

    return fragment; 

}

我QuestionFragment onCreateView是按文件:

public View onCreateView(
     LayoutInflater inflater, 
     ViewGroup container, 
     Bundle questionData) { 

    this.rootView = inflater.inflate(
      R.layout.layout_question_template, 
      container, 
      false); 

    Bundle args = getArguments(); 
    this.question = (Question) args.getSerializable(QuestionFragment.QUESTION); 
    populateInflatable(); 

    rootView.findViewById(R.id.layout_question_template_root).setTag(this.question.getID()); 
    return rootView; 
} 

populateInflatable我用this.rootViewfintViewById,並填充它我的問題數據。然後我改變一個按鈕的顏色,如果從問題中選擇了一個。

在按鈕點擊我打電話selectAnserButton

public void selectAnswerButton(View selectedButton) { 
    int questionId = 
      (int) this.activityRoot.findViewById(
        R.id.layout_question_template_root).getTag(); //?? 
    unSelectAllButtons(); 
    changeColor(selectedButton); 
    Repository.findById(questionId).selectAnswer(selectedButton.getId()); 
} 

unSelectAllButtons代表的四個按鈕buttonToUnSelect.getBackground().clearColorFilter();。和Repository只是一個static類與示例問題數據。

當我有更多的一個視圖時,這一切都非常錯誤。在每個片段上,我使用相同的視圖ID對相同的xml進行膨脹,因爲我已經定義了它們。而且現在我明白了,要求findViewById檢索不到一個,但是從我目前檢索到的那個Id的所有視圖,也從我的上一個和下一個fragment中檢索。所以每次我想選擇我當前的fragment的視圖,我也會修改上一個和下一個fragments中的相同視圖。你可以想象這是如何產生問題的。這讓我覺得我有一個根本的錯誤,因爲我不認爲應該有更多的ViewID相同。

我真的不明白我應該如何使用ViewPager來做到這一點。在這一點上,我覺得我正在試圖製作一個木雕,但相反,我正在將這個框架劈成碎片。 ViewPager必須有更好的方法。

已解決:感謝Soo Chun Jung爲我指出了答案。總之,它爲我工作的是:

  1. 將我的Question model id傳遞給Bundle的每個片段。
  2. 將每個片段存儲在ArrayMap內部,片段位置爲key,片段爲value
  3. 從我的selectAnswer函數獲取每個單獨的片段現在很容易:首先獲取當前片段的位置,然後調用getter函數,該函數返回當前位置上的片段。
  4. 既然我有片段,我可以輕鬆地更改它的按鈕,因爲它們保留爲專用字段,並分配在'onCreateView`方法中。
+0

這將會是有用的,如果你能表現出[MCVE] –

+0

'如何正確使用android' ViewPager - https://developer.android.com/reference/android/support/v4/view/ ViewPager.html& https://developer.android.com/training/animation/screen-slide.html –

+0

此外,它聽起來像你需要了解RadioButton。 https://developer.android.com/guide/topics/ui/controls/radiobutton.html – Gary99

回答

1

希望這是有幫助〜



適配器

class CustomAdapter extends FragmentPagerAdapter { 
private final String[] TITLES = {"A", "B"}; 
private final String TAG = CustomAdapter.class.getSimpleName(); 

private final ArrayList<Fragment> mFragments; 

private final FragmentManager fm; 

public CustomAdapter(FragmentManager fm) { 
    super(fm); 
    mFragments = new ArrayList<>(getCount()); 
    this.fm = fm; 
} 


@Override 
public CharSequence getPageTitle(int position) { 
    return TITLES[position]; 
} 

@Override 
public int getCount() { 
    return TITLES.length; 
} 

@Override 
public void destroyItem(ViewGroup container, int position, Object object) { 
    Log.d(TAG, "destroyItem position = " + position); 
    mFragments.remove(object); 
    super.destroyItem(container, position, object); 
} 

@Override 
public Object instantiateItem(ViewGroup container, int position) { 
    Object object = super.instantiateItem(container, position); 
    mFragments.add((Fragment) object); 
    return object; 
} 

@Override 
public Fragment getItem(int position) { 
    Log.d(TAG, "getItem position = " + position); 
    if (position == 0) { 
     return MyFragmentA.newInstance(); 
    } else if (position == 1) { 
     return MyFragmentB.newInstance(); 
    } 
    return null; 
} 

public MyFragmentA getMyFragmentA() { 
    synchronized (mFragments) { 
     for (Fragment f : mFragments) { 
      if (f instanceof MyFragmentA) { 
       return (MyFragmentA) f; 
      } 
     } 
    } 
    return null; 
} 

public MyFragmentB getMyFragmentB() { 
    synchronized (mFragments) { 
     for (Fragment f : mFragments) { 
      if (f instanceof MyFragmentB) { 
       return (MyFragmentB) f; 
      } 
     } 
    } 
    return null; 
} 
} 



片段類

public class MyFragmentB extends Fragment { 

... 


    public updateYourUI(){ 
     //update something 
    } 
} 



使用

mPager = (CustomViewPager) findViewById(R.id.pager); 
mAdapter = new CustomAdapter(getChildFragmentManager()); 
mPager.setAdapter(mAdapter); 


mAdapter.getMyFragmentB().updateYourUI(); 

下面的評論如果你只有一種片段。你可以修改一些這樣的功能。

public static MyFragmentB newInstance(int ID) { 
    MyFragmentB fragment = new MyFragmentB(); 
    Bundle bundle = new Bundle(); 
    bundle.putInt("ID", ID); 
    fragment.setArguments(bundle); 
    return fragment; 
} 

@Override 
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    myID = getArguments().getInt("ID"); 
    .... 
} 

public int getMyID() { 
    return myID; 
} 





public MyFragmentB getMyFragmentByID(String id) { 
    synchronized (mFragments) { 
     for (Fragment f : mFragments) { 
      if (f instanceof MyFragmentB) { 
       MyFragmentB temp = (MyFragmentB)f; 
       if(temp.getID.equals(id){ 
        return (MyFragmentB) f; 
       } 

      } 
     } 
    } 
    return null; 
} 
+0

感謝您的回答。我會盡快嘗試。我不明白爲什麼'getItem'硬編碼的具體數量的項目?另外我怎樣才能使用Fragment實例來更新我的用戶界面?這將解決很多問題,但我也查看了「Fragment」文檔,但無法找到答案。 – Alex

+0

剛剛有一個想法:如果我在'onCreateView'方法中將每個片段的UI視圖設置爲他的私有字段,那麼在我訪問當前視圖片段之後,我可以通過獲取器訪問這些視圖片段。這會起作用嗎? – Alex

+0

然而,我的問題是,我有相同的'片段'的多個實例。那麼我怎麼能區分它們呢?我需要爲片段本身設置某種標識。 – Alex