代码之家  ›  专栏  ›  技术社区  ›  Vinayak B

确定片段重新启动是由于屏幕旋转还是浏览页面滑动?

  •  6
  • Vinayak B  · 技术社区  · 7 年前

    我有一个 Activity 具有 ViewPager . 这个 查看寻呼机 有很多页,就像一本书。每个片段都有 RecyclerViews 内容丰富。下面是我的用例

    1-当我滑动页面时,RecyclerView必须从列表的开头开始。 2、如果我旋转我的设备,它应该从旋转前我离开的确切最后位置读取。

    如果我不使用任何逻辑,第二个场景就可以完美地工作。即,旋转。但不是第一种情况。

    如果我做一些如下逻辑。有助于实现第一个场景,但不能实现第二个场景。

      @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        if (savedInstanceState==null) {
            mIsFirstTime = true;
        }
    }
    
    @Override
    public void onResume() {
        super.onResume();
        try {
            getActivity().invalidateOptionsMenu();
                if (!mIsFirstTime) {
                    mListView.scrollToPosition(0);                
                }
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    }
    

    所以我的问题是

    如何确定片段重新启动是由于屏幕旋转或浏览页面滑动造成的?

    我已经试过了 onConfigurationChanged(Configuration newConfig) . 但这对我没有帮助。你能帮帮我吗

    4 回复  |  直到 6 年前
        1
  •  2
  •   azizbekian    6 年前

    从…起 a comment of OP :

    我的问题是我怎么知道的 onSaveInstanceState() 由于屏幕方向更改而不是片段重新启动而调用

    你可以通过 Activity#isChangingConfigurations() 应用程序编程接口。

    
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
    
            if (isChangingConfigurations()) {
                // this callback is executed as a result of a configuration change (e.g. orientation change)
            } else {
                // no configuration change happens (e.g. a click on a home button would end up here)
            }
        }
    
    

    现在可以将布尔值保存到 Bundle outState 和相应的设置UI:

    
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putBoolean("isConfigurationChange", isChangingConfigurations());
        }
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // initialization logics here
    
            if (savedInstanceState != null) {
                boolean isConfigurationChange = savedInstanceState.getBoolean("isConfigurationChange");
    
                // if `onCreate` is called as a result of configuration change
                if (isConfigurationChange) {
                    // view hierarchy is not yet laid out, have to post an action 
                    listView.post(new Runnable() {
                        @Override
                        public void run() {
                            // we are guaranteed, that `listView` is already laid out
                            listView.scrollToPosition(0);
                        }
                    });
                }
            }
        }
    
    

    注意,在内部执行布尔值检查逻辑 onResume() 是一个bug(按下主页按钮并导航回应用程序会导致再次滚动到顶部,这是不需要的)。相反 onCreate() 应选择为正确的回调。

        2
  •  1
  •   Manoj Perumarath    7 年前

    我认为您可以声明一个变量,并在滑动操作时将状态检查为true。

    viewPager.addOnPageChangeListener(new OnPageChangeListener() {
    public void onPageScrollStateChanged(int state) {}
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
    
    public void onPageSelected(int position) {
    // here assign the variable to true;
    // This method will get called only after a swipe action is invoked on 
    //viewpager.  
     }});
    

    在片段中检查变量 状态为true ,如果不是从方向生成,则重置 变量为false .

    快乐编码:)

        3
  •  0
  •   Tomin B Azhakathu    6 年前

    在片段和视图寻呼机中使用 onSaveInstanceState() 函数并使用保存的实例滚动到旧位置。

    如果要保留的UI数据简单且轻量级,则可以 可以单独使用onSaveInstanceState()来保存状态数据。在里面 如果需要保留复杂数据,可以 使用ViewModel对象的组合,onSaveInstanceState() 方法和持久本地存储。

    参考 Saving UI States

    使用示例 onSaveInstanceState()

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        if (savedInstanceState==null) {
                if(savedInstanceState.containsKey("position")){
                    int positon = savedInstanceState.getInt("position",0);
                    YOUR_RECYCLER_VIEW.scrollToPosition(positon);
            }
        }
    }
    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("position",YOUR_RECYLER_VIEW.getVerticalScrollbarPosition());
    }
    

    在此处了解更多信息

    1. How to use onSaveInstanceState() and onRestoreInstanceState()?

    2. Android Developers Official Documention

    要了解viewpage的页面更改,请使用

    myViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
            //Use your logic here.
    
            }
    
            @Override
            public void onPageSelected(int position) {
    
            //Use your logic here.
    
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
    
            //Use your logic here.
    
            }
        });
    
        4
  •  0
  •   yozhik    6 年前

    为什么要滚动到零位置?mListView。滚动位置(0);

    我认为您可以在片段暂停时保存RecyclerView的当前位置,然后在重新创建后,转到该位置。