我已经构建了一个在Android 4.2-4.4上完美运行的应用程序,但现在我需要为4.1和4.0可能的用户提供支持。我在Android清单文件中将minSDKVersion设置为15。我有一个viewpager,每个片段都有一个动作菜单。此操作菜单上的其中一个按钮(单个勾号)可以显示和隐藏viewpager中的每个页面,具体取决于onActivityCreated方法中的一些布尔变量。我遇到的问题是,每当我打开viewpager时,第一页都没有显示此菜单项。如果我滑动到下一页然后再返回,则会显示。这在Android 4.2或更高版本中不会发生,所以我认为使用嵌套片段可能是一个问题,但我不知道为什么它只是在第一页上出现问题。
我的应用程序的结构:主要活动 - > ListFragment - > ListFragment - > ViewPager
图标图片:i.stack.imgur.com/LtuFG.png
部分代码:
ViewPager:
package com.dremq.dremq.activities;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.*;
import android.widget.ListView;
import com.dremq.dremq.R;
import com.dremq.dremq.model.*;
import com.viewpagerindicator.CirclePageIndicator;
import com.dremq.dremq.model.CustomMethods;
import java.util.ArrayList;
public class ViewPagerFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
super.onCreateOptionsMenu(menu, menuInflater);
menuInflater.inflate(R.menu.marking_options_menu, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
// option to mark the entire quiz
case R.id.markAll:
// make modifications to database
// notify the adapter that data has changed to force a UI update.
adapter.notifyDataSetChanged();
// invalidate the options menu to force a reload of the menu.
getActivity().invalidateOptionsMenu();
return true;
// option to reset the entire quiz
case R.id.reset:
// set reset to true to enforce the correct function in getItemPosition
reset = true;
// make modifications to database
// notify the adapter that data has changed to force a UI update.
adapter.notifyDataSetChanged();
// set reset to false to stop getItemPosition from running the incorrect function
reset = false;
// invalidate the options menu to force a reload of the menu.
getActivity().invalidateOptionsMenu();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
DatabaseManager.createDatabase(getActivity());
// Get the data past from the previous fragment.
Bundle bundle = getArguments();
// If there is data in the bundle then extract the Quiz ID and load the correct Question and Attempt data
if (bundle != null){
quizID = bundle.getInt("QUIZ_ID");
// if this quiz not been attempted before then add it as a new attempt in the database.
if (!Query_Attempt.attemptedBefore(quizID)){
Query_Attempt.addAttempt(quizID);
attemptID = Query_Attempt.getLastAttemptID(quizID);
Query_AttemptQuestion.addMultipleAttemptQuestion(attemptID, questionList);
}
// get the id for the last attempt at this quiz
attemptID = Query_Attempt.getLastAttemptID(quizID);
markedAll = Query_Attempt.isComplete(attemptID);
}
// get the viewpager container from the UI.
viewPager = (ViewPager) view.findViewById(R.id.pager);
// Getting the adaptor by passing the fragment manager.
adapter = new SlidingPagerAdapter(getChildFragmentManager());
viewPager.setAdapter(adapter);
}
public class SlidingPagerAdapter extends android.support.v4.app.FragmentStatePagerAdapter{
public SlidingPagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment fragment = new QuestionItemFragment();
// Create a new Bundle object to transfer any required data e.g, the id of the clicked item.
Bundle bundle = new Bundle();
bundle.putInt("QUESTION_ID", questionList.get(position).getQuestionID());
bundle.putInt("ATTEMPT_ID", attemptID);
fragment.setArguments(bundle);
return fragment;
}
@Override
public int getCount() {
return questionList.size();
}
@Override
public int getItemPosition(Object object){
// get the fragment for the specific viewpager item from the object.
QuestionItemFragment f = (QuestionItemFragment) object;
if (f != null) {
if (reset){
f.reset(attemptID);
}else{
f.update();
}
}
return super.getItemPosition(object);
}
}
}
ViewPagerItem:
package com.dremq.dremq.activities;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.*;
import android.widget.*;
import com.dremq.dremq.R;
import com.dremq.dremq.animation.ExpandAnimation;
import com.dremq.dremq.model.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class ViewPagerItem extends Fragment implements Updateable, Resetable{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
super.onCreateOptionsMenu(menu, menuInflater);
menuInflater.inflate(R.menu.marking_single_options_menu, menu);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
DatabaseManager.createDatabase(getActivity());
// Get the data past from the previous fragment.
Bundle bundle = getArguments();
// If there is data in the bundle then extract the question and attempt ID and load the correct question data
if (bundle != null){
// check if the question is complete
complete = Query_AttemptQuestion.isComplete(attemptQuestionID);
if (complete){
correctOptionIDs = Query_Question_Option.getCorrectIDsList(questionID);
markedAll = Query_Attempt.isComplete(attemptID);
getActivity().invalidateOptionsMenu();
}
}
list = (ListView)getView().findViewById(R.id.list);
// Getting the adaptor by passing the ArrayList containing the data.
adaptor = new OptionMenuAdaptor(getActivity(), question_info.getOptions());
list.setAdapter(adaptor);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
// option to mark a single question.
case R.id.markSingle:
Log.i("markSingle", "Mark single question");
// set complete to true so that UI can be corrected.
complete = true;
// notify the adapter that data has changed to force a UI update.
adaptor.notifyDataSetChanged();
// invalidate the options menu to force a reload of the menu.
getActivity().invalidateOptionsMenu();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onPrepareOptionsMenu (Menu menu) {
super.onPrepareOptionsMenu(menu);
// complete shows that the question is marked so hide the mark single question option
if (complete){
menu.findItem(R.id.markSingle).setVisible(false);
}
// marked all shows that the entire quiz is marked so hide the option to mark quiz and show reset button
if (markedAll){
menu.findItem(R.id.markAll).setVisible(false);
menu.findItem(R.id.reset).setVisible(true);
}
}
private class OptionMenuAdaptor extends BaseAdapter {
private ArrayList<Option> data;
private LayoutInflater inflater = null;
private int height;
private ArrayList<Boolean> expanded;
public OptionMenuAdaptor(Activity activity, ArrayList<Option> data) {
this.data = data;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public View getView(final int position, View convertView, final ViewGroup parent) {
View view = convertView;
if (view == null) {
view = inflater.inflate(R.layout.option_list_item, null);
}
// get the view for the option text
final CheckedTextView optionText = (CheckedTextView)view.findViewById(R.id.option_text);
final ListView listView = ((ListView) parent);
// Retrieve the data from the ArrayList used to populate the particular data item.
final Option option_info = data.get(position);
// set the correct text for this individual item.
optionText.setText(option_info.getOptionText());
if (complete){
// set up the views for a marked question
}else{
// set up the views for a unmarked question
}
return view;
}
}
}
ListFragment:
package com.dremq.dremq.activities;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import com.dremq.dremq.R;
import com.dremq.dremq.model.*;
import de.timroes.android.listview.EnhancedListView;
import java.util.ArrayList;
public class QuizMenuFragment extends Fragment {
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
DatabaseManager.createDatabase(getActivity());
// Get the data past from the previous fragment.
Bundle bundle = getArguments();
// If there is data in the bundle then extract the category ID and load the correct Quiz data
if (bundle != null){
categoryID = bundle.getInt("CATEGORY_ID");
quizList = Query_Quiz.getQuizzes(categoryID);
}
// find the list layout view in the current layout.
list = (EnhancedListView)getView().findViewById(R.id.list);
// Getting the adaptor by passing the ArrayList containing the data.
adaptor = new QuizMenuAdaptor(getActivity(), quizList);
list.setAdapter(adaptor);
String[] category = Query_Category.getCategory("User");
// Implements the click event for a single menu item. This creates a new Question Option fragment and passes it the Quiz ID.
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
android.support.v4.app.Fragment fragment = new QuestionOptionFragment();
// Create a new Bundle object to transfer any required data e.g, the id of the clicked item.
Bundle bundle = new Bundle();
bundle.putInt("QUIZ_ID", quizList.get(position).getQuizID());
fragment.setArguments(bundle);
// Begin the transaction to change fragments.
android.support.v4.app.FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
// Set which layout container is having the view changed.
fragmentTransaction.replace(((ViewGroup)getView().getParent()).getId(), fragment); // can be used to load the correct layout when using this class as a generic class e.g. in exam builder and in categories list.
// add the item to the back stack allowing the user to return to this view by clicking the back button
fragmentTransaction.addToBackStack(null);
// set the transition animation
fragmentTransaction.setTransition(android.support.v4.app.FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// commit the transition and show the changes to the user.
fragmentTransaction.commit();
}
});
}
}
}
我已经尝试过了:
总结 - 动作栏项目未显示在viewpager的第一页上,但会在您滑动到下一页并返回后显示。这仅适用于早于4.2的Android版本。