操作菜单项未显示在适用于Android 4.2之前的viewpager的第一页上

时间:2014-09-03 21:45:15

标签: android android-fragments android-actionbar

我已经构建了一个在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();
            }
        });

    }
}

}

我已经尝试过了:

  • 从使用support-v13.jar更改为support-v4.jar
  • 将每页中加载的菜单添加到viewpager中加载的菜单中。这是我原来的,但不幸的是,这产生了一个类似的问题,即当项目应该被隐藏时,有一个空白区域显示为最右边的项目,再次只在第一页上,并且可以修复&#39;通过滑动到下一页然后再回来。
  • 将菜单移至MainActivity - 类似的问题,现在双重勾选图标不显示在第一页上,但会在您滑动到下一页并返回时显示。
  • 直接加载viewpager作为第一个片段(即绕过两个列表视图) - 这有效!
  • 加载一个ListFragment,然后加载ViewPager - 发生相同的问题

总结 - 动作栏项目未显示在viewpager的第一页上,但会在您滑动到下一页并返回后显示。这仅适用于早于4.2的Android版本。

0 个答案:

没有答案