【问题标题】:Set OnClick Listener on Action Bar Title in Android在 Android 中的操作栏标题上设置 OnClick 侦听器
【发布时间】:2014-09-10 08:49:58
【问题描述】:

我正在开发使用ActionBar 的android 应用程序,所以有一个导航抽屉图标可以打开它,ActionBar 中的标题为ActionBar。我想在ActionBar 的标题上设置一个点击侦听器,以便它启动一个新的Activity 并在导航抽屉图标上设置不同的点击侦听器以打开导航抽屉菜单。

我点击了导航抽屉图标,但是当我点击 ActionBar 标题的标题时,它也会打开导航抽屉菜单。有没有办法在ActionBar的标题上设置不同的点击监听器。

提前致谢。

【问题讨论】:

标签: android android-actionbar android-appcompat android-actionbar-compat android-actionbaractivity


【解决方案1】:

我知道为时已晚,但是对于像这样使用SupportActionBar 并且仍然没有找到干净解决方案的人来说:

Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

对于没有徽标和自定义视图的默认配置,第一项(索引 0)将是 Home/Back ImageView,第二项将是我们的 Title TextView,第三项将是 OptionMenu Imageview。

在索引 1 处获取子项将返回标题。为孩子添加OnClickListener 将使其像chram 一样工作:

    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    toolbar.getChildAt(1).setOnClickListener(v -> {
       // title is clicked, call ur function here
       
       // can also verify that the view is title itself by converting it to textview
       try {
            String title  = ((TextView)v).getText().toString();
            // title will be your activity title 
        } catch (Exception e) {
            e.printStackTrace();
            // if you got an exception, the view is not title. 
            // Check changing the index, in case you have custom views in the toolbar.
        }
    });

【讨论】:

    【解决方案2】:

    我知道在这里发表评论已经很晚了,但是当我搜索如何为操作栏标题添加 OnClick 时遇到了这个问题。 以下是我发现并为我工作的内容,希望对像我这样的人有所帮助。

    我为我的应用程序中的一个片段编写了它。

            ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
            actionBar.setTitle(""); 
            ((AppCompatActivity) getActivity()).setSupportActionBar((Toolbar) getActivity().findViewById(R.id.toolbar));
            TextView toolbarTitle = (TextView) getActivity().findViewById(R.id.toolbarTitle);
            toolbarTitle.setText("New title");
            toolbarTitle.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                  // Action bar title clicked
                }
            });
            actionBar.show();
    

    【讨论】:

      【解决方案3】:

      如果您想使用当前存在的 ActionBar 而不是 Toolbar,请使用以下内容:

      ActionBar actBar = getSupportActionBar();
      if(actBar != null) {
          actBar.setTitle(R.string.your_ab_title);
       }
      
      //Set actions to take when the AB is clicked
      Toolbar ab = findViewById(R.id.action_bar);
      if(ab != null){
          for (int i= 0; i < ab.getChildCount(); i++){
      
              View child = ab.getChildAt(i);
      
              if(child instanceof TextView || child instanceof ImageView) {
                  child.setOnClickListener(new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          String url = "http://www.HoverDroids.com";
      
                          Intent i = new Intent(Intent.ACTION_VIEW);
                          i.setData(Uri.parse(url));
                          startActivity(i);
                      }
                  });
              }
           }
      }    
      

      【讨论】:

        【解决方案4】:

        您可以使用工具栏轻松完成此操作。在布局 xml 文件中定义工具栏,如下所示:

            <android.support.v7.widget.Toolbar
            android:id="@+id/MainActivityToolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" >
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent" >
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="@string/app_name"
                    android:textSize="30sp"
                    tools:ignore="RelativeOverlap"
        
                    android:layout_marginTop="10dp"
                    android:layout_marginBottom="10dp"
                    android:layout_marginRight="10dp"
                    android:layout_marginLeft="10dp"
                    />
                <Button
                    android:id="@+id/LogOutButton"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:layout_alignParentEnd="true"
                    android:layout_alignParentRight="true"
        
                    android:layout_marginTop="10dp"
                    android:layout_marginBottom="10dp"
                    android:layout_marginRight="10dp"
                    android:layout_marginLeft="10dp"
        
                    android:text="@string/logout" />
            </RelativeLayout>
        
        </android.support.v7.widget.Toolbar>
        

        然后你可以使用这段代码在Activity中设置监听器:

        setSupportActionBar((Toolbar) findViewById(R.id.MainActivityToolbar));
        
        logOutButton =  findViewById(R.id.LogOutButton);
        logOutButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           //define your function for logout or something else 
           LogOut();
         }
        });
        

        【讨论】:

          【解决方案5】:

          如果您知道标题中的实际文本,并且您有理由确定屏幕上没有其他 TextView 共享该标题,则可以使用递归视图树搜索来查找它。

          这是一个很好的解决方案,因为它不需要反映如何构建工具栏的内部知识,并且可以让您直接访问TextView

          @Nullable
          public static TextView findTextViewWithText(@Nullable View toCheck, String toFind) {
          
              if (toCheck instanceof TextView) {
                  String foundText = ((TextView) toCheck).getText().toString();
                  if (foundText.equals(toFind)) {
                      return (TextView) toCheck;
                  }
          
              } else if (toCheck instanceof ViewGroup) {
                  for (int i = 0; i < ((ViewGroup) toCheck).getChildCount(); i++) {
                      TextView found = findTextViewWithText(((ViewGroup) toCheck).getChildAt(i), toFind);
                      if (found != null) {
                          return found;
                      }
                  }
              }
              return null;
          }
          

          最可靠的调用视图是装饰视图,但请随意尝试最适合您的目的,您的里程可能会有所不同。

          View found = findTextViewWithText(
              getActivity().getWindow().getDecorView(), "My Title");
          if (found != null) {
            // Do something, like set a click listener
          }
          

          【讨论】:

            【解决方案6】:

            我认为Simas's answer 是最好的,但如果你喜欢,这里有一个hacky 版本。

            ViewTools.findActionBarTitle(getWindow().getDecorView()).setOnClickListener(...);
            

            这个应该是通用,因为它适用于:

            • 库存安卓ActionBar
            • Theme.AppCompat支持ActionBar
            • v21 风格setActionBar
              使用&lt;Toolbar android:id="@+id/action_bar"
              或将膨胀的Toolbar 传递为root
            • v21 风格setSupportActionBar
              使用&lt;android.support.v7.widget.Toolbar android:id="@id/action_bar"
              或将膨胀的Toolbar 传递为root
            • 自定义Toolbar 实现可能需要稍作调整,
              但是您可以将其封装在该自定义类中。

            虽然我只测试了 support:v22。

            /** @param root usually Activity.getWindow().getDecorView() or your custom Toolbar */
            public static @Nullable View findActionBarTitle(@NonNull View root) {
                return findActionBarItem(root, "action_bar_title", "mTitleTextView");
            }
            /** @param root usually Activity.getWindow().getDecorView() or your custom Toolbar */
            public static @Nullable View findActionBarSubTitle(@NonNull View root) {
                return findActionBarItem(root, "action_bar_subtitle", "mSubtitleTextView");
            }
            
            private static @Nullable View findActionBarItem(@NonNull View root,
                    @NonNull String resourceName, @NonNull String toolbarFieldName) {
                View result = findViewSupportOrAndroid(root, resourceName);
            
                if (result == null) {
                    View actionBar = findViewSupportOrAndroid(root, "action_bar");
                    if (actionBar != null) {
                        result = reflectiveRead(actionBar, toolbarFieldName);
                    }
                }
                if (result == null && root.getClass().getName().endsWith("widget.Toolbar")) {
                    result = reflectiveRead(root, toolbarFieldName);
                }
                return result;
            }
            
            @SuppressWarnings("ConstantConditions")
            private static @Nullable View findViewSupportOrAndroid(@NonNull View root, @NonNull String resourceName) {
                Context context = root.getContext();
                View result = null;
                if (result == null) {
                    int supportID = context.getResources().getIdentifier(resourceName, "id", context.getPackageName());
                    result = root.findViewById(supportID);
                }
                if (result == null) {
                    int androidID = context.getResources().getIdentifier(resourceName, "id", "android");
                    result = root.findViewById(androidID);
                }
                return result;
            }
            
            @SuppressWarnings("unchecked")
            public static <T> @Nullable T reflectiveRead(@NonNull Object object, @NonNull String fieldName) {
                try {
                    Field field = object.getClass().getDeclaredField(fieldName);
                    field.setAccessible(true);
                    return (T)field.get(object);
                } catch (Exception ex) {
                    Log.w("HACK", "Cannot read " + fieldName + " in " + object, ex);
                }
                return null;
            }
            

            【讨论】:

            • resourceName 是否有可能在支持库的未来版本中发生变化?
            • @bwicks 不太可能,但是是的。这可能无关紧要,因为资源名称在编译时被锁定。因此,即使他们发布了新的支持库版本,您的应用程序也应该是安全的,因为它包含旧版本。也就是说,在您更新依赖项之前,构建并重新发布。还要注意R.id.action_bar_title 是公共资源,而android.R.id.action_bar_title 是镜像的,不是(这就是使用getIdentifier 的原因)。您应该更关心的是Android平台更改了编译时保护不适用的名称。
            【解决方案7】:

            您可以使用工具栏轻松完成此操作。在布局 xml 文件中定义工具栏,如下所示:

             <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                android:background="?colorPrimary"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
            
                <TextView
                    android:id="@+id/toolbarTitle"
                    style="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
                    android:background="?attr/selectableItemBackground"
                    android:layout_width="wrap_content"
                    android:gravity="center_vertical"
                    android:layout_height="match_parent" />
            </android.support.v7.widget.Toolbar>
            

            然后你可以使用这段代码在Activity中设置监听器:

            setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
            
            TextView toolbarTitle= (TextView) findViewById(R.id.toolbarTitle);
            toolbarTitle.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // DO SOMETHING HERE
                    }
                });
            

            【讨论】:

              【解决方案8】:

              如果您使用支持 v7:21 的工具栏。 查看以下代码:

              Field titleField = Toolbar.class.getDeclaredField("mTitleTextView");
                      titleField.setAccessible(true);
                      TextView barTitleView = (TextView) titleField.get(mToolbar);
                      barTitleView.setOnClickListener(new OnClickListener() {
              
                          @Override
                          public void onClick(View v) {
                              // TODO Auto-generated method stub
              
                          }
                      });
              

              【讨论】:

                【解决方案9】:

                您可以为标题使用自定义布局并为其分配监听器:

                @Override
                protected void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                
                    ActionBar actionBar = getActionBar();
                    if (actionBar != null) {
                        // Disable the default and enable the custom
                        actionBar.setDisplayShowTitleEnabled(false);
                        actionBar.setDisplayShowCustomEnabled(true);
                        View customView = getLayoutInflater().inflate(R.layout.actionbar_title, null);
                        // Get the textview of the title
                        TextView customTitle = (TextView) customView.findViewById(R.id.actionbarTitle);
                
                
                        // Change the font family (optional)
                        customTitle.setTypeface(Typeface.MONOSPACE);
                        // Set the on click listener for the title
                        customTitle.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Log.w("MainActivity", "ActionBar's title clicked.");
                            }
                        });
                        // Apply the custom view
                        actionBar.setCustomView(customView);
                    }
                }
                

                actionbar_title.xml

                <LinearLayout
                    xmlns:android="http://schemas.android.com/apk/res/android"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center">
                
                    <TextView
                        android:id="@+id/actionbarTitle"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:textSize="25sp"
                        android:text="@string/app_name"/>
                
                </LinearLayout>
                

                【讨论】:

                • 遗憾的是,这样你就失去了getActionBar().setTitle() 的能力,你也需要自己实现字幕处理,否则这是正确的解决方案。如果有人发布 ActionBarTitles 的要点作为支持标题/副标题并阅读主题的插入式替换自定义视图,那就太好了。
                【解决方案10】:

                尝试在 onCreate() 函数下添加此代码。这将获取操作栏标题所在的资源,并为其分配一个 ID,您可以使用它来添加 OnClickListener。告诉我进展如何!

                final int abTitleId = getResources().getIdentifier("action_bar_title", "id", "android");
                findViewById(abTitleId).setOnClickListener(new View.OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    //Do something
                    }
                });
                

                【讨论】:

                • 您好,这种方法在 Android OS 2.3 中不起作用,不确定 4.0-4.3,我测试它在 Android 4.4.4 中有效。请帮忙
                • @Williams 2.3 没有操作栏。如果您使用 appcompat-v7,则可以使用:your.R.id.action_bar_title 而不是 getIdentifier。您可以要求两个 ID 并使用存在的 ID。
                • Android 4.0+ 错误
                • @Max 检查我的new answer,如果您仍有问题。 (v21中的工具栏没有设置id,可以是read via reflection
                • 我尝试了同样的方法..但它在标题字段上显示空指针异常..我将 abtitleId 的 id 作为某个数值...但由于 null 仍然 onclick 实现失败参考
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-01-02
                • 1970-01-01
                • 1970-01-01
                • 2012-11-09
                • 2021-10-09
                相关资源
                最近更新 更多