Skip to content

Commit e8c2549

Browse files
committed
修复左右标题过长的情况下出现闪烁的问题
1 parent 632fb12 commit e8c2549

File tree

7 files changed

+113
-70
lines changed

7 files changed

+113
-70
lines changed

.github/ISSUE_TEMPLATE/issue_template_bug.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ assignees: getActivity
2222

2323
* 出现问题的安卓版本【必填】:请填写出现问题的 Android 版本
2424

25+
* 问题信息的来源渠道【必填】:请填写问题的来源(例如:自己遇到的/Bugly 看到的/用户反馈等等)
26+
2527
#### 请回答
2628

2729
* 是部分机型还是所有机型都会出现【必答】:部分/全部(例如:某为,某 Android 版本会出现)

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# 标题栏框架
22

3-
* 项目地址:[Github](https://github.com/getActivity/TitleBar)[码云](https://gitee.com/getActivity/TitleBar)
3+
* 项目地址:[Github](https://github.com/getActivity/TitleBar)
44

55
* 博客地址:[Android标题栏(TitleBar)绝佳解决方案](https://www.jianshu.com/p/617be02dc265)
66

7-
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/TitleBar/releases/download/9.5/TitleBar.apk)
7+
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/TitleBar/releases/download/9.6/TitleBar.apk)
88

99
![](picture/demo_code.png)
1010

@@ -51,7 +51,7 @@ android {
5151
5252
dependencies {
5353
// 标题栏框架:https://github.com/getActivity/TitleBar
54-
implementation 'com.github.getActivity:TitleBar:9.5'
54+
implementation 'com.github.getActivity:TitleBar:9.6'
5555
}
5656
```
5757

@@ -250,6 +250,8 @@ public class XxxApplication extends Application {
250250

251251
* Android 代码规范:[AndroidCodeStandard](https://github.com/getActivity/AndroidCodeStandard) ![](https://img.shields.io/github/stars/getActivity/AndroidCodeStandard.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidCodeStandard.svg)
252252

253+
* Android 资源大汇总:[AndroidIndex](https://github.com/getActivity/AndroidIndex) ![](https://img.shields.io/github/stars/getActivity/AndroidIndex.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidIndex.svg)
254+
253255
* Android 开源排行榜:[AndroidGithubBoss](https://github.com/getActivity/AndroidGithubBoss) ![](https://img.shields.io/github/stars/getActivity/AndroidGithubBoss.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidGithubBoss.svg)
254256

255257
* Studio 精品插件:[StudioPlugins](https://github.com/getActivity/StudioPlugins) ![](https://img.shields.io/github/stars/getActivity/StudioPlugins.svg) ![](https://img.shields.io/github/forks/getActivity/StudioPlugins.svg)

app/build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ android {
77
applicationId "com.hjq.bar.demo"
88
minSdkVersion 17
99
targetSdkVersion 31
10-
versionCode 95
11-
versionName "9.5"
10+
versionCode 96
11+
versionName "9.6"
1212
}
1313

1414
// 支持 JDK 1.8
@@ -61,8 +61,8 @@ dependencies {
6161
implementation 'com.google.android.material:material:1.4.0'
6262

6363
// 吐司工具类:https://github.com/getActivity/ToastUtils
64-
implementation 'com.github.getActivity:ToastUtils:10.3'
64+
implementation 'com.github.getActivity:ToastUtils:10.5'
6565

6666
// 内存泄漏捕捉:https://github.com/square/leakcanary
67-
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
67+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
6868
}

app/src/main/res/layout/activity_main.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,15 @@
315315

316316
</com.hjq.bar.TitleBar>
317317

318+
<com.hjq.bar.TitleBar
319+
android:layout_width="wrap_content"
320+
android:layout_height="wrap_content"
321+
android:layout_marginTop="20dp"
322+
app:leftIcon="@null"
323+
app:leftTitle="我是很长很长的文案"
324+
app:rightTitle="我是很长很长的文案"
325+
app:title="默认的标题栏" />
326+
318327
</LinearLayout>
319328

320329
</FrameLayout>

library/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ android {
55

66
defaultConfig {
77
minSdkVersion 16
8-
versionCode 95
9-
versionName "9.5"
8+
versionCode 96
9+
versionName "9.6"
1010
}
1111

1212
// 支持 JDK 1.8
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.hjq.bar;
22

3-
import android.view.View;
4-
53
/**
64
* author : Android 轮子哥
75
* github : https://github.com/getActivity/TitleBar
@@ -11,17 +9,23 @@
119
public interface OnTitleBarListener {
1210

1311
/**
14-
* 左项被点击
12+
* 左边的标题被点击
13+
*
14+
* @param titleBar 标题栏对象(非空)
1515
*/
1616
default void onLeftClick(TitleBar titleBar) {}
1717

1818
/**
19-
* 标题被点击
19+
* 中间的标题被点击
20+
*
21+
* @param titleBar 标题栏对象(非空)
2022
*/
2123
default void onTitleClick(TitleBar titleBar) {}
2224

2325
/**
24-
* 右项被点击
26+
* 右边的标题被点击
27+
*
28+
* @param titleBar 标题栏对象(非空)
2529
*/
2630
default void onRightClick(TitleBar titleBar) {}
2731
}

library/src/main/java/com/hjq/bar/TitleBar.java

Lines changed: 82 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
*/
3030
@SuppressWarnings({"unused", "UnusedReturnValue"})
3131
public class TitleBar extends FrameLayout
32-
implements View.OnClickListener,
33-
View.OnLayoutChangeListener {
32+
implements View.OnClickListener {
3433

3534
private static final String LOG_TAG = "TitleBar";
3635

@@ -275,7 +274,8 @@ public TitleBar(Context context, AttributeSet attrs, int defStyleAttr) {
275274
addView(mRightView, 2);
276275
addView(mLineView, 3);
277276

278-
addOnLayoutChangeListener(this);
277+
addOnLayoutChangeListener(mConstraintChildViewWidthListener);
278+
addOnLayoutChangeListener(mLimitChildViewStatusListener);
279279

280280
// 如果当前是布局预览模式
281281
if (isInEditMode()) {
@@ -291,56 +291,6 @@ public TitleBar(Context context, AttributeSet attrs, int defStyleAttr) {
291291
}
292292
}
293293

294-
/**
295-
* {@link View.OnLayoutChangeListener}
296-
*/
297-
298-
@Override
299-
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
300-
// 先移除当前的监听,因为 TextView.setMaxWidth 方法会重新触发监听
301-
removeOnLayoutChangeListener(this);
302-
303-
// 标题栏子 View 最大宽度限制算法
304-
post(() -> {
305-
// 这里要延迟执行,否则会导致子 View.getWidth 的时候为零
306-
int barWidth = right - left;
307-
int sideWidth = Math.max(mLeftView.getWidth(), mRightView.getWidth());
308-
int maxWidth = sideWidth * 2 + mTitleView.getWidth();
309-
// 算出来子 View 的宽大于标题栏的宽度
310-
if (maxWidth >= barWidth) {
311-
// 判断是左右项太长还是标题项太长
312-
if (sideWidth > barWidth / 3) {
313-
// 如果是左右项太长,那么按照比例进行划分
314-
TitleBarSupport.setMaxWidth(mLeftView, barWidth / 4);
315-
TitleBarSupport.setMaxWidth(mTitleView, barWidth / 2);
316-
TitleBarSupport.setMaxWidth(mRightView, barWidth / 4);
317-
} else {
318-
// 如果是标题项太长,那么就进行动态计算
319-
TitleBarSupport.setMaxWidth(mLeftView, sideWidth);
320-
TitleBarSupport.setMaxWidth(mTitleView, barWidth - sideWidth * 2);
321-
TitleBarSupport.setMaxWidth(mRightView, sideWidth);
322-
}
323-
} else {
324-
// 不限制子 View 的最大宽度
325-
TitleBarSupport.setMaxWidth(mLeftView, Integer.MAX_VALUE);
326-
TitleBarSupport.setMaxWidth(mTitleView, Integer.MAX_VALUE);
327-
TitleBarSupport.setMaxWidth(mRightView, Integer.MAX_VALUE);
328-
}
329-
330-
// 解决在外部触摸时触发点击效果的问题
331-
mLeftView.setClickable(true);
332-
mTitleView.setClickable(true);
333-
mRightView.setClickable(true);
334-
// TextView 里面必须有东西才能被点击
335-
mLeftView.setEnabled(TitleBarSupport.isContainContent(mLeftView));
336-
mTitleView.setEnabled(TitleBarSupport.isContainContent(mTitleView));
337-
mRightView.setEnabled(TitleBarSupport.isContainContent(mRightView));
338-
339-
// 这里再次监听需要延迟,否则会导致递归的情况发生
340-
addOnLayoutChangeListener(TitleBar.this);
341-
});
342-
}
343-
344294
/**
345295
* {@link View.OnClickListener}
346296
*/
@@ -701,7 +651,7 @@ public TitleBar setRightIconTint(int color) {
701651
}
702652

703653
/**
704-
* 清楚标题的图标着色器
654+
* 清除标题的图标着色器
705655
*/
706656
public TitleBar clearTitleIconTint() {
707657
mTitleIconTint = TitleBarSupport.NO_COLOR;
@@ -710,7 +660,7 @@ public TitleBar clearTitleIconTint() {
710660
}
711661

712662
/**
713-
* 清楚左标题的图标着色器
663+
* 清除左标题的图标着色器
714664
*/
715665
public TitleBar clearLeftIconTint() {
716666
mLeftIconTint = TitleBarSupport.NO_COLOR;
@@ -719,7 +669,7 @@ public TitleBar clearLeftIconTint() {
719669
}
720670

721671
/**
722-
* 清楚右标题的图标着色器
672+
* 清除右标题的图标着色器
723673
*/
724674
public TitleBar clearRightIconTint() {
725675
mRightIconTint = TitleBarSupport.NO_COLOR;
@@ -930,4 +880,80 @@ public ITitleBarStyle getCurrentStyle() {
930880
public static void setDefaultStyle(ITitleBarStyle style) {
931881
sGlobalStyle = style;
932882
}
883+
884+
private final View.OnLayoutChangeListener mConstraintChildViewWidthListener = new OnLayoutChangeListener() {
885+
886+
@Override
887+
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
888+
// 暂时先移除当前的监听,因为 TextView.setMaxWidth 方法会重新触发监听
889+
removeOnLayoutChangeListener(this);
890+
891+
// 标题栏子 View 最大宽度限制算法
892+
post(() -> {
893+
// 这里要延迟执行,否则会导致子 View.getWidth 的时候为零
894+
int titleBarWidth = right - left;
895+
int leftViewWidth = mLeftView.getWidth();
896+
int centerViewWidth = mTitleView.getWidth();
897+
int rightViewWidth = mRightView.getWidth();
898+
899+
int maxEdgeWidth = Math.max(leftViewWidth, rightViewWidth);
900+
int calculateTotalWidth = maxEdgeWidth * 2 + centerViewWidth;
901+
// 算出来子 View 的宽大于标题栏的宽度
902+
if (calculateTotalWidth >= titleBarWidth) {
903+
// 判断是左右项太长还是标题项太长
904+
if (maxEdgeWidth > titleBarWidth / 3) {
905+
// 如果是左右项太长,那么按照比例进行划分
906+
TitleBarSupport.setMaxWidth(mLeftView, titleBarWidth / 4);
907+
TitleBarSupport.setMaxWidth(mTitleView, titleBarWidth / 2);
908+
TitleBarSupport.setMaxWidth(mRightView, titleBarWidth / 4);
909+
} else {
910+
// 如果是标题项太长,那么就进行动态计算
911+
TitleBarSupport.setMaxWidth(mLeftView, maxEdgeWidth);
912+
TitleBarSupport.setMaxWidth(mTitleView, titleBarWidth - maxEdgeWidth * 2);
913+
TitleBarSupport.setMaxWidth(mRightView, maxEdgeWidth);
914+
}
915+
} else {
916+
// 不限制子 View 的最大宽度
917+
TitleBarSupport.setMaxWidth(mLeftView, Integer.MAX_VALUE);
918+
TitleBarSupport.setMaxWidth(mTitleView, Integer.MAX_VALUE);
919+
TitleBarSupport.setMaxWidth(mRightView, Integer.MAX_VALUE);
920+
}
921+
922+
removeCallbacks(mAddOnLayoutChangeListenerRunnable);
923+
// 这里再次监听需要延迟,否则会导致递归的情况发生
924+
post(mAddOnLayoutChangeListenerRunnable);
925+
});
926+
}
927+
};
928+
929+
@SuppressWarnings("all")
930+
private final View.OnLayoutChangeListener mLimitChildViewStatusListener = new OnLayoutChangeListener() {
931+
932+
@Override
933+
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
934+
// 解决在外部触摸时触发点击效果的问题
935+
if (!mLeftView.isClickable()) {
936+
mLeftView.setClickable(true);
937+
}
938+
if (!mTitleView.isClickable()) {
939+
mTitleView.setClickable(true);
940+
}
941+
if (!mRightView.isClickable()) {
942+
mRightView.setClickable(true);
943+
}
944+
945+
// TextView 里面必须有东西才能被点击
946+
if (!mLeftView.isEnabled()) {
947+
mLeftView.setEnabled(TitleBarSupport.isContainContent(mLeftView));
948+
}
949+
if (!mTitleView.isEnabled()) {
950+
mTitleView.setEnabled(TitleBarSupport.isContainContent(mTitleView));
951+
}
952+
if (!mRightView.isEnabled()) {
953+
mRightView.setEnabled(TitleBarSupport.isContainContent(mRightView));
954+
}
955+
}
956+
};
957+
958+
private final Runnable mAddOnLayoutChangeListenerRunnable = () -> addOnLayoutChangeListener(mConstraintChildViewWidthListener);
933959
}

0 commit comments

Comments
 (0)