Skip to content

Commit

Permalink
修复标题过长在某些机型上面会出现重叠的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
getActivity committed Dec 31, 2022
1 parent e8c2549 commit 087443b
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 118 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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'
}
```

Expand Down
8 changes: 4 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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'
}
25 changes: 22 additions & 3 deletions app/src/main/java/com/hjq/bar/demo/MainActivity.java
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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
Expand All @@ -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();
}
}
18 changes: 14 additions & 4 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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" />

<com.hjq.bar.TitleBar
Expand Down Expand Up @@ -192,7 +192,7 @@
app:titleSize="20sp" />

<com.hjq.bar.TitleBar
android:id="@+id/tb_main_bar"
android:id="@+id/tb_main_bar_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
Expand Down Expand Up @@ -320,10 +320,20 @@
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:leftIcon="@null"
app:leftTitle="我是很长很长的文案"
app:rightTitle="我是很长很长的文案"
app:leftTitle="我是很长很长很长很长很长的文案"
app:rightTitle="我是很长很长很长很长很长的文案"
app:title="默认的标题栏" />

<com.hjq.bar.TitleBar
android:id="@+id/tb_main_bar_long_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:leftIcon="@null"
app:leftTitle="我是测试文案我是测试文案我是测试文案"
app:rightTitle="我是测试文案我是测试文案我是测试文案"
app:title="我是很长很长很长很长很长的标题" />

</LinearLayout>

</FrameLayout>
Expand Down
4 changes: 2 additions & 2 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ android {

defaultConfig {
minSdkVersion 16
versionCode 96
versionName "9.6"
versionCode 1000
versionName "10.0"
}

// 支持 JDK 1.8
Expand Down
148 changes: 69 additions & 79 deletions library/src/main/java/com/hjq/bar/TitleBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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()) {
Expand All @@ -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}
*/
Expand Down Expand Up @@ -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);
}
10 changes: 0 additions & 10 deletions library/src/main/java/com/hjq/bar/TitleBarSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
33 changes: 19 additions & 14 deletions library/src/main/java/com/hjq/bar/style/CommonBarStyle.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 "";
}

Expand Down

0 comments on commit 087443b

Please sign in to comment.