From 087443baebc8ba15efdaa972ab088a8d29875845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Android=20=E8=BD=AE=E5=AD=90=E5=93=A5?= Date: Sat, 31 Dec 2022 16:42:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=A0=87=E9=A2=98=E8=BF=87?= =?UTF-8?q?=E9=95=BF=E5=9C=A8=E6=9F=90=E4=BA=9B=E6=9C=BA=E5=9E=8B=E4=B8=8A?= =?UTF-8?q?=E9=9D=A2=E4=BC=9A=E5=87=BA=E7=8E=B0=E9=87=8D=E5=8F=A0=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- app/build.gradle | 8 +- .../java/com/hjq/bar/demo/MainActivity.java | 25 ++- app/src/main/res/layout/activity_main.xml | 18 ++- library/build.gradle | 4 +- .../src/main/java/com/hjq/bar/TitleBar.java | 148 ++++++++---------- .../java/com/hjq/bar/TitleBarSupport.java | 10 -- .../com/hjq/bar/style/CommonBarStyle.java | 33 ++-- 8 files changed, 132 insertions(+), 118 deletions(-) diff --git a/README.md b/README.md index eb8d0c1..675cec0 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ * 博客地址:[Android标题栏(TitleBar)绝佳解决方案](https://www.jianshu.com/p/617be02dc265) -* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/TitleBar/releases/download/9.6/TitleBar.apk) +* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/TitleBar/releases/download/10.0/TitleBar.apk) ![](picture/demo_code.png) @@ -51,7 +51,7 @@ android { dependencies { // 标题栏框架:https://github.com/getActivity/TitleBar - implementation 'com.github.getActivity:TitleBar:9.6' + implementation 'com.github.getActivity:TitleBar:10.0' } ``` diff --git a/app/build.gradle b/app/build.gradle index 929c39d..497135f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.hjq.bar.demo" minSdkVersion 17 targetSdkVersion 31 - versionCode 96 - versionName "9.6" + versionCode 1000 + versionName "10.0" } // 支持 JDK 1.8 @@ -61,8 +61,8 @@ dependencies { implementation 'com.google.android.material:material:1.4.0' // 吐司工具类:https://github.com/getActivity/ToastUtils - implementation 'com.github.getActivity:ToastUtils:10.5' + implementation 'com.github.getActivity:ToastUtils:11.2' // 内存泄漏捕捉:https://github.com/square/leakcanary - debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10' } \ No newline at end of file diff --git a/app/src/main/java/com/hjq/bar/demo/MainActivity.java b/app/src/main/java/com/hjq/bar/demo/MainActivity.java index 9e0adf1..8048650 100644 --- a/app/src/main/java/com/hjq/bar/demo/MainActivity.java +++ b/app/src/main/java/com/hjq/bar/demo/MainActivity.java @@ -1,7 +1,8 @@ package com.hjq.bar.demo; import android.os.Bundle; -import android.view.View; +import android.os.Handler; +import android.os.Looper; import androidx.appcompat.app.AppCompatActivity; @@ -15,14 +16,16 @@ * time : 2018/08/17 * desc : TitleBar 使用案例 */ -public final class MainActivity extends AppCompatActivity { +public final class MainActivity extends AppCompatActivity implements Runnable { + + private static final Handler HANDLER = new Handler(Looper.getMainLooper()); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - TitleBar titleBar = findViewById(R.id.tb_main_bar); + TitleBar titleBar = findViewById(R.id.tb_main_bar_click); titleBar.setOnTitleBarListener(new OnTitleBarListener() { @Override @@ -40,5 +43,21 @@ public void onRightClick(TitleBar titleBar) { ToastUtils.show("右项 View 被点击"); } }); + + HANDLER.postDelayed(this, 2000); + } + + @Override + public void run() { + TitleBar titleBar = findViewById(R.id.tb_main_bar_long_title); + titleBar.setLeftTitle("左边"); + titleBar.setTitle("我是很长很长很长很长很长很长很长很长的标题"); + titleBar.setRightTitle("右边"); + } + + @Override + protected void onDestroy() { + HANDLER.removeCallbacks(this); + super.onDestroy(); } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b428d17..33e6dea 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -100,10 +100,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" - app:childVerticalPadding="15dp" app:leftIcon="@null" app:title="标题向左对齐并且加粗" app:titleGravity="start" + app:titleHorizontalPadding="20dp" app:titleStyle="bold" /> + + diff --git a/library/build.gradle b/library/build.gradle index f11f7d1..c2f45f8 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -5,8 +5,8 @@ android { defaultConfig { minSdkVersion 16 - versionCode 96 - versionName "9.6" + versionCode 1000 + versionName "10.0" } // 支持 JDK 1.8 diff --git a/library/src/main/java/com/hjq/bar/TitleBar.java b/library/src/main/java/com/hjq/bar/TitleBar.java index 0484d2a..6264df4 100644 --- a/library/src/main/java/com/hjq/bar/TitleBar.java +++ b/library/src/main/java/com/hjq/bar/TitleBar.java @@ -29,7 +29,8 @@ */ @SuppressWarnings({"unused", "UnusedReturnValue"}) public class TitleBar extends FrameLayout - implements View.OnClickListener { + implements View.OnClickListener, + View.OnLayoutChangeListener { private static final String LOG_TAG = "TitleBar"; @@ -274,8 +275,7 @@ public TitleBar(Context context, AttributeSet attrs, int defStyleAttr) { addView(mRightView, 2); addView(mLineView, 3); - addOnLayoutChangeListener(mConstraintChildViewWidthListener); - addOnLayoutChangeListener(mLimitChildViewStatusListener); + addOnLayoutChangeListener(this); // 如果当前是布局预览模式 if (isInEditMode()) { @@ -291,6 +291,72 @@ public TitleBar(Context context, AttributeSet attrs, int defStyleAttr) { } } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + // 如果当前是布局预览模式,避免影响布局预览 + if (isInEditMode()) { + return; + } + + int titleBarWidth = this.getMeasuredWidth(); + int leftViewWidth = mLeftView.getMeasuredWidth(); + int centerViewWidth = mTitleView.getMeasuredWidth(); + int rightViewWidth = mRightView.getMeasuredWidth(); + + int maxEdgeWidth = Math.max(leftViewWidth, rightViewWidth); + int calculateTotalWidth = maxEdgeWidth * 2 + centerViewWidth; + // 算出来总宽度是否大于标题栏的宽度 + if (calculateTotalWidth <= titleBarWidth) { + return; + } + + // 判断是左右项太长还是标题项太长 + if (maxEdgeWidth > titleBarWidth / 3) { + // 如果是左右项太长,那么就进行动态计算 + measureChildWithMargins(mLeftView, MeasureSpec.makeMeasureSpec(titleBarWidth / 4, MeasureSpec.EXACTLY), 0, + MeasureSpec.makeMeasureSpec(mLeftView.getMeasuredHeight(), MeasureSpec.EXACTLY), 0); + measureChildWithMargins(mTitleView, MeasureSpec.makeMeasureSpec(titleBarWidth / 2, MeasureSpec.EXACTLY), 0, + MeasureSpec.makeMeasureSpec(mTitleView.getMeasuredHeight(), MeasureSpec.EXACTLY), 0); + measureChildWithMargins(mRightView, MeasureSpec.makeMeasureSpec(titleBarWidth / 4, MeasureSpec.EXACTLY), 0, + MeasureSpec.makeMeasureSpec(mRightView.getMeasuredHeight(), MeasureSpec.EXACTLY), 0); + } else { + // 如果是标题项太长,那么就进行动态计算 + measureChildWithMargins(mLeftView, MeasureSpec.makeMeasureSpec(maxEdgeWidth, MeasureSpec.EXACTLY), 0, + MeasureSpec.makeMeasureSpec(mLeftView.getMeasuredHeight(), MeasureSpec.EXACTLY), 0); + measureChildWithMargins(mTitleView, MeasureSpec.makeMeasureSpec(titleBarWidth - maxEdgeWidth * 2, MeasureSpec.EXACTLY), 0, + MeasureSpec.makeMeasureSpec(mTitleView.getMeasuredHeight(), MeasureSpec.EXACTLY), 0); + measureChildWithMargins(mRightView, MeasureSpec.makeMeasureSpec(maxEdgeWidth, MeasureSpec.EXACTLY), 0, + MeasureSpec.makeMeasureSpec(mRightView.getMeasuredHeight(), MeasureSpec.EXACTLY), 0); + } + } + + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { + // 解决在外部触摸时触发点击效果的问题 + if (!mLeftView.isClickable()) { + mLeftView.setClickable(true); + } + if (!mTitleView.isClickable()) { + mTitleView.setClickable(true); + } + if (!mRightView.isClickable()) { + mRightView.setClickable(true); + } + + // TextView 里面必须有东西才能被点击 + if (!mLeftView.isEnabled()) { + mLeftView.setEnabled(TitleBarSupport.isContainContent(mLeftView)); + } + if (!mTitleView.isEnabled()) { + mTitleView.setEnabled(TitleBarSupport.isContainContent(mTitleView)); + } + if (!mRightView.isEnabled()) { + mRightView.setEnabled(TitleBarSupport.isContainContent(mRightView)); + } + } + /** * {@link View.OnClickListener} */ @@ -880,80 +946,4 @@ public ITitleBarStyle getCurrentStyle() { public static void setDefaultStyle(ITitleBarStyle style) { sGlobalStyle = style; } - - private final View.OnLayoutChangeListener mConstraintChildViewWidthListener = new OnLayoutChangeListener() { - - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - // 暂时先移除当前的监听,因为 TextView.setMaxWidth 方法会重新触发监听 - removeOnLayoutChangeListener(this); - - // 标题栏子 View 最大宽度限制算法 - post(() -> { - // 这里要延迟执行,否则会导致子 View.getWidth 的时候为零 - int titleBarWidth = right - left; - int leftViewWidth = mLeftView.getWidth(); - int centerViewWidth = mTitleView.getWidth(); - int rightViewWidth = mRightView.getWidth(); - - int maxEdgeWidth = Math.max(leftViewWidth, rightViewWidth); - int calculateTotalWidth = maxEdgeWidth * 2 + centerViewWidth; - // 算出来子 View 的宽大于标题栏的宽度 - if (calculateTotalWidth >= titleBarWidth) { - // 判断是左右项太长还是标题项太长 - if (maxEdgeWidth > titleBarWidth / 3) { - // 如果是左右项太长,那么按照比例进行划分 - TitleBarSupport.setMaxWidth(mLeftView, titleBarWidth / 4); - TitleBarSupport.setMaxWidth(mTitleView, titleBarWidth / 2); - TitleBarSupport.setMaxWidth(mRightView, titleBarWidth / 4); - } else { - // 如果是标题项太长,那么就进行动态计算 - TitleBarSupport.setMaxWidth(mLeftView, maxEdgeWidth); - TitleBarSupport.setMaxWidth(mTitleView, titleBarWidth - maxEdgeWidth * 2); - TitleBarSupport.setMaxWidth(mRightView, maxEdgeWidth); - } - } else { - // 不限制子 View 的最大宽度 - TitleBarSupport.setMaxWidth(mLeftView, Integer.MAX_VALUE); - TitleBarSupport.setMaxWidth(mTitleView, Integer.MAX_VALUE); - TitleBarSupport.setMaxWidth(mRightView, Integer.MAX_VALUE); - } - - removeCallbacks(mAddOnLayoutChangeListenerRunnable); - // 这里再次监听需要延迟,否则会导致递归的情况发生 - post(mAddOnLayoutChangeListenerRunnable); - }); - } - }; - - @SuppressWarnings("all") - private final View.OnLayoutChangeListener mLimitChildViewStatusListener = new OnLayoutChangeListener() { - - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - // 解决在外部触摸时触发点击效果的问题 - if (!mLeftView.isClickable()) { - mLeftView.setClickable(true); - } - if (!mTitleView.isClickable()) { - mTitleView.setClickable(true); - } - if (!mRightView.isClickable()) { - mRightView.setClickable(true); - } - - // TextView 里面必须有东西才能被点击 - if (!mLeftView.isEnabled()) { - mLeftView.setEnabled(TitleBarSupport.isContainContent(mLeftView)); - } - if (!mTitleView.isEnabled()) { - mTitleView.setEnabled(TitleBarSupport.isContainContent(mTitleView)); - } - if (!mRightView.isEnabled()) { - mRightView.setEnabled(TitleBarSupport.isContainContent(mRightView)); - } - } - }; - - private final Runnable mAddOnLayoutChangeListenerRunnable = () -> addOnLayoutChangeListener(mConstraintChildViewWidthListener); } \ No newline at end of file diff --git a/library/src/main/java/com/hjq/bar/TitleBarSupport.java b/library/src/main/java/com/hjq/bar/TitleBarSupport.java index 79d03cf..143364f 100644 --- a/library/src/main/java/com/hjq/bar/TitleBarSupport.java +++ b/library/src/main/java/com/hjq/bar/TitleBarSupport.java @@ -211,14 +211,4 @@ public static Typeface getTextTypeface(int style) { return Typeface.DEFAULT; } } - - /** - * 设置 TextView 的最大宽度 - */ - public static void setMaxWidth(TextView view, int maxPixels) { - if (view.getMaxWidth() == maxPixels) { - return; - } - view.setMaxWidth(maxPixels); - } } \ No newline at end of file diff --git a/library/src/main/java/com/hjq/bar/style/CommonBarStyle.java b/library/src/main/java/com/hjq/bar/style/CommonBarStyle.java index b7d641c..a57bc85 100644 --- a/library/src/main/java/com/hjq/bar/style/CommonBarStyle.java +++ b/library/src/main/java/com/hjq/bar/style/CommonBarStyle.java @@ -108,21 +108,26 @@ public int getChildVerticalPadding(Context context) { @Override public CharSequence getTitle(Context context) { // 如果当前上下文对象是 Activity,就获取 Activity 的 label 属性作为标题栏的标题 - if (context instanceof Activity) { - // 获取清单文件中的 android:label 属性值 - CharSequence label = ((Activity) context).getTitle(); - if (!TextUtils.isEmpty(label)) { - try { - PackageManager packageManager = context.getPackageManager(); - PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0); - // 如果当前 Activity 没有设置 android:label 属性,则默认会返回 App 名称,则需要过滤掉 - if (!label.toString().equals(packageInfo.applicationInfo.loadLabel(packageManager).toString())) { - // 设置标题 - return label; - } - } catch (PackageManager.NameNotFoundException ignored) {} - } + if (!(context instanceof Activity)) { + return ""; + } + + // 获取清单文件中的 android:label 属性值 + CharSequence label = ((Activity) context).getTitle(); + if (TextUtils.isEmpty(label)) { + return ""; } + + try { + PackageManager packageManager = context.getPackageManager(); + PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0); + // 如果当前 Activity 没有设置 android:label 属性,则默认会返回 App 名称,则需要过滤掉 + if (!label.toString().equals(packageInfo.applicationInfo.loadLabel(packageManager).toString())) { + // 设置标题 + return label; + } + } catch (PackageManager.NameNotFoundException ignored) {} + return ""; }