【问题标题】:Android CollapsingToolbarLayout collapse ListenerAndroid CollapsingToolbarLayout 折叠监听器
【发布时间】:2015-10-19 08:43:09
【问题描述】:

我正在使用CollapsingToolBarLayout 以及AppBarLayoutCoordinatorLayout,它们完全可以正常工作。我将我的Toolbar 设置为在向上滚动时固定,我想知道是否有办法更改工具栏的标题文本,当 CollapsingToolBarLayout 它被折叠时。

总结一下,当滚动展开时,我想要两个不同的标题

提前谢谢大家

【问题讨论】:

    标签: android android-design-library android-collapsingtoolbarlayout


    【解决方案1】:

    OnOffsetChangedListener 连接到您的AppBarLayout。当verticalOffset达到0或小于Toolbar高度时,说明CollapsingToolbarLayout已经折叠,否则正在展开或展开。

    mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
                @Override
                public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                    if(verticalOffset == 0 || verticalOffset <= mToolbar.getHeight() && !mToolbar.getTitle().equals(mCollapsedTitle)){
                        mCollapsingToolbar.setTitle(mCollapsedTitle);
                    }else if(!mToolbar.getTitle().equals(mExpandedTitle)){
                        mCollapsingToolbar.setTitle(mExpandedTitle);
                    }
    
                }
            });
    

    【讨论】:

    • 它对我不起作用。 OnCollapse 我想启用主页按钮并在展开时隐藏主页按钮
    • 工具栏完全展开时,verticalOffset 值似乎为零,然后在折叠时变为负数。当工具栏收起时,verticalOffset 等于工具栏高度的负数 (-mToolbar.getHeight())。所以...工具栏部分展开“if (verticalOffset > -mToolbar.getHeight())”
    • 如果有人想知道appBarLayout.getVerticalOffset() 方法在哪里,您可以调用appBarLayout.getY() 来检索回调中使用的相同值。
    • 不幸的是,Jarett Millard 不对。根据您的 fitSystemWindow 配置和 StatusBar 配置(透明)appBarLayout.getY() 可能是 verticalOffset = appBarLayout.getY() + statusBarHeight
    • 有没有人注意到即使我们实际上并没有与 appbar 交互,是否会重复调用 mAppBarLayout.addOnOffsetChangedListener(listener)?或者这是我观察到这种行为的布局/应用程序中的一个错误。请帮忙!
    【解决方案2】:

    这个解决方案对我有用:

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
      if (i == 0) {
        if (onStateChangeListener != null && state != State.EXPANDED) {
          onStateChangeListener.onStateChange(State.EXPANDED);
        }
        state = State.EXPANDED;
      } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
        if (onStateChangeListener != null && state != State.COLLAPSED) {
          onStateChangeListener.onStateChange(State.COLLAPSED);
        }
        state = State.COLLAPSED;
      } else {
        if (onStateChangeListener != null && state != State.IDLE) {
          onStateChangeListener.onStateChange(State.IDLE);
        }
        state = State.IDLE;
      }
    }
    

    在 AppBarLayout 上使用 addOnOffsetChangedListener。

    【讨论】:

    • 你能分享你的完整代码吗?什么是 State.EXPANDED 等?
    【解决方案3】:
    private enum State {
        EXPANDED,
        COLLAPSED,
        IDLE
    }
    
    private void initViews() {
        final String TAG = "AppBarTest";
        final AppBarLayout mAppBarLayout = findViewById(R.id.appbar);
        mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            private State state;
    
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (verticalOffset == 0) {
                    if (state != State.EXPANDED) {
                        Log.d(TAG,"Expanded");
                    }
                    state = State.EXPANDED;
                } else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) {
                    if (state != State.COLLAPSED) {
                        Log.d(TAG,"Collapsed");
                    }
                    state = State.COLLAPSED;
                } else {
                    if (state != State.IDLE) {
                        Log.d(TAG,"Idle");
                    }
                    state = State.IDLE;
                }
            }
        });
    }
    

    【讨论】:

      【解决方案4】:

      我分享基于@Frodio Beggins 和@Nifhel 代码的完整实现:​​

      public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {
      
          public enum State {
              EXPANDED,
              COLLAPSED,
              IDLE
          }
      
          private State mCurrentState = State.IDLE;
      
          @Override
          public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
              if (i == 0) {
                  if (mCurrentState != State.EXPANDED) {
                      onStateChanged(appBarLayout, State.EXPANDED);
                  }
                  mCurrentState = State.EXPANDED;
              } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
                  if (mCurrentState != State.COLLAPSED) {
                      onStateChanged(appBarLayout, State.COLLAPSED);
                  }
                  mCurrentState = State.COLLAPSED;
              } else {
                  if (mCurrentState != State.IDLE) {
                      onStateChanged(appBarLayout, State.IDLE);
                  }
                  mCurrentState = State.IDLE;
              }
          }
      
          public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
      }
      

      然后你就可以使用它了:

      appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
          @Override
          public void onStateChanged(AppBarLayout appBarLayout, State state) {
              Log.d("STATE", state.name());
          }
      });
      

      【讨论】:

      • 没错。但请不要使用 Proguard 将枚举转换为整数值。
      • 我不知道。太好了!
      • 枚举也是确保类型安全的一种非常好的方法。您不能拥有 State.IMPLODED 因为它不存在(编译器会抱怨),但是使用整数常量,您可以使用编译器不知道是错误的值。他们也很适合单身人士,但那是另一回事了。
      • @droppin_science for android enums check out IntDef
      • @DavidDarias 就我个人而言,我发现枚举是一种更简洁的方法,即使它们的开销也是如此(此处开始参数... :-)
      【解决方案5】:

      这段代码对我有用

      mAppBarLayout.addOnOffsetChangedListener(new   AppBarLayout.OnOffsetChangedListener() {
              @Override
              public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                  if (verticalOffset == -mCollapsingToolbarLayout.getHeight() + mToolbar.getHeight()) {
                      //toolbar is collapsed here
                      //write your code here
                  }
              }
          });
      

      【讨论】:

      • 比 Nikola Despotoski 更好的答案
      • 似乎不是一个可靠的解决方案。我对其进行了测试,我的设备上的值如下:mCollapsingToolbarLayout.getHeight() = 1013, mToolbar.getHeight() = 224。因此根据您的解决方案,折叠状态下的垂直偏移必须为 -789,但它等于 -693
      【解决方案6】:

      这个解决方案非常适合我检测AppBarLayout 折叠或展开。

      appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
              @Override
              public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
      
                  if (Math.abs(verticalOffset)-appBarLayout.getTotalScrollRange() == 0)
                  {
                      //  Collapsed
      
      
                  }
                  else
                  {
                      //Expanded
      
      
                  }
              }
          });
      

      AppBarLayout 上使用addOnOffsetChangedListener

      【讨论】:

      • 这起火灾在多个场合崩溃了,在展开时也是如此。
      【解决方案7】:

      如果你使用的是 CollapsingToolBarLayout 你可以放这个

      collapsingToolbar.setExpandedTitleColor(ContextCompat.getColor(activity, android.R.color.transparent));
      collapsingToolbar.setTitle(title);
      

      【讨论】:

        【解决方案8】:

        您可以使用以下方法获取 collapsingToolBar alpha 百分比:

        appbarLayout.addOnOffsetChangedListener( new AppBarLayout.OnOffsetChangedListener() {
                @Override
                public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                    float percentage = ((float)Math.abs(verticalOffset)/appBarLayout.getTotalScrollRange());
                    fadedView.setAlpha(percentage);
            });
        

        供参考:link

        【讨论】:

        • 这是一个很好的答案,因为它提供了一个标准化的偏移量。在我看来,API 应该直接提供这个而不是 verticalOffset 像素距离。
        • 我想当 AppBarLayout 折叠时隐藏视图并显示展开视图。所以我使用val percentage = 1 - abs(verticalOffset).toFloat() / appBarLayout.totalScrollRange。对我来说效果很好。
        【解决方案9】:

        这段代码非常适合我。您可以使用百分比比例您喜欢的方式

        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            double percentage = (double) Math.abs(verticalOffset) / collapsingToolbar.getHeight();
            if (percentage > 0.8) {
                collapsingToolbar.setTitle("Collapsed");
            } else {
                collapsingToolbar.setTitle("Expanded");
            }
        }
        

        【讨论】:

          【解决方案10】:

          我的工具栏偏移值在折叠时得到 -582,在展开时=0 所以我通过在 Toast 中设置 offsetvalue 来找到价值并相应地更改代码。

           mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
                  @Override
                  public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                      if(verticalOffset == -582) {
                      Toast.makeText(MainActivity.this, "collaped" + verticalOffset, Toast.LENGTH_SHORT).show();
                      mCollapsingToolbarLayout.setTitle("Collapsed");
                      }else if(verticalOffset == 0){
                          Toast.makeText(MainActivity.this, "expanded" + verticalOffset, Toast.LENGTH_SHORT).show();
                      mCollapsingToolbarLayout.setTitle("expanded");
                      }
                  }
              });
          

          【讨论】:

            【解决方案11】:

            这是一个 Kotlin 解决方案。将OnOffsetChangedListener 添加到AppBarLayout

            方法一:

            AppBarStateChangeListener.kt 添加到您的项目中:

            import com.google.android.material.appbar.AppBarLayout
            import kotlin.math.abs
            
            abstract class AppBarStateChangeListener : AppBarLayout.OnOffsetChangedListener {
            
                enum class State {
                    EXPANDED, COLLAPSED, IDLE
                }
            
                private var mCurrentState = State.IDLE
            
                override fun onOffsetChanged(appBarLayout: AppBarLayout, i: Int) {
                    if (i == 0 && mCurrentState != State.EXPANDED) {
                        onStateChanged(appBarLayout, State.EXPANDED)
                        mCurrentState = State.EXPANDED
                    }
                    else if (abs(i) >= appBarLayout.totalScrollRange && mCurrentState != State.COLLAPSED) {
                        onStateChanged(appBarLayout, State.COLLAPSED)
                        mCurrentState = State.COLLAPSED
                    }
                    else if (mCurrentState != State.IDLE) {
                        onStateChanged(appBarLayout, State.IDLE)
                        mCurrentState = State.IDLE
                    }
                }
            
                abstract fun onStateChanged(
                    appBarLayout: AppBarLayout?,
                    state: State?
                )
            
            }
            

            将监听器添加到您的appBarLayout

            appBarLayout.addOnOffsetChangedListener(object: AppBarStateChangeListener() {
                    override fun onStateChanged(appBarLayout: AppBarLayout?, state: State?) {
                        Log.d("State", state.name)
                        when(state) {
                            State.COLLAPSED -> { /* Do something */ }
                            State.EXPANDED -> { /* Do something */ }
                            State.IDLE -> { /* Do something */ }
                        }
                    }
                }
            )
            

            方法B:

            appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
                    if (abs(verticalOffset) - appBarLayout.totalScrollRange == 0) { 
                        // Collapsed
                    } else if (verticalOffset == 0) {
                        // Expanded
                    } else {
                        // Idle
                    }
                }
            )
            

            【讨论】:

              【解决方案12】:

              这是 Kotlin 中的解决方案:

              abstract class AppBarStateChangeListener : OnOffsetChangedListener {
                  enum class State {
                      EXPANDED, COLLAPSED, IDLE
                  }
              
                  private var mCurrentState =
                      State.IDLE
              
                  override fun onOffsetChanged(appBarLayout: AppBarLayout, i: Int) {
                      mCurrentState = if (i == 0) {
                          if (mCurrentState != State.EXPANDED) {
                              onStateChanged(appBarLayout, State.EXPANDED)
                          }
                          State.EXPANDED
                      } else if (Math.abs(i) >= appBarLayout.totalScrollRange) {
                          if (mCurrentState != State.COLLAPSED) {
                              onStateChanged(appBarLayout, State.COLLAPSED)
                          }
                          State.COLLAPSED
                      } else {
                          if (mCurrentState != State.IDLE) {
                              onStateChanged(appBarLayout, State.IDLE)
                          }
                          State.IDLE
                      }
                  }
              
                  abstract fun onStateChanged(
                      appBarLayout: AppBarLayout?,
                      state: State?
                  )
              }
              

              这里是监听器:

                appbar.addOnOffsetChangedListener(object : AppBarStateChangeListener() {
                      override fun onStateChanged(
                          appBarLayout: AppBarLayout?,
                          state: State?
                      ) {
                          if(state == State.COLLAPSED){
                              LayoutBottom.visibility = View.GONE
                          }else if(state == State.EXPANDED){
                              LayoutBottom.visibility = View.VISIBLE
                          }
                      }
                  })
              

              【讨论】:

                猜你喜欢
                • 2014-07-17
                • 1970-01-01
                • 2016-03-06
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-11-28
                相关资源
                最近更新 更多