效果:
实现原理
-
底层:一个ListView,顶部图片是这个ListView的Header
-
中间层:Toolbar,控制背景色透明度渐变
-
上层:标题TextView,控制缩放大小,及X,Y轴位移
布局文件
activity_main.xml
正如上面所言,RelativeLayout放置了一个ListView,一个Toolbar(顶部),一个TextView(缩放标题)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<RelativeLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<ListView
android:id=
"@+id/lv_main"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
android:id=
"@+id/tb_main"
android:layout_width=
"match_parent"
android:layout_height=
"?attr/actionBarSize"
app:popupTheme=
"@style/ThemeOverlay.AppCompat.Light"
app:theme=
"@style/ThemeOverlay.AppCompat.Dark.ActionBar"
tools:background=
"@android:color/black"
/>
<TextView
android:id=
"@+id/tv_main_title"
style=
"@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:padding=
"@dimen/padding_medium"
android:text=
"@string/toolbar_title"
android:textColor=
"@android:color/white"
android:textSize=
"@dimen/float_title_size_large"
/>
</RelativeLayout>
|
header.xml
ListView的Header布局文件,只有一个ImageView。
1
2
3
4
5
6
7
8
9
10
11
|
<FrameLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"@dimen/header_height"
>
<ImageView
android:id=
"@+id/img_header_bg"
android:layout_width=
"match_parent"
android:scaleType=
"centerCrop"
android:layout_height=
"match_parent"
android:src=
"@mipmap/header_bg"
/>
</FrameLayout>
|
代码控制
MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
public class MainActivity extends ActionBarActivity implements AbsListView.OnScrollListener {
//控件
private ListView listView;
private Toolbar toolbar;
private TextView floatTitle;
private ImageView headerBg;
//测量值
private float headerHeight;
//顶部高度
private float minHeaderHeight;
//顶部最低高度,即Bar的高度
private float floatTitleLeftMargin;
//header标题文字左偏移量
private float floatTitleSize;
//header标题文字大小
private float floatTitleSizeLarge;
//header标题文字大小(大号)
@Override
protected void onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initMeasure();
initView();
initListViewHeader();
initListView();
initEvent();
}
private void initMeasure() {
headerHeight = getResources().getDimension(R.dimen.header_height);
minHeaderHeight = getResources().getDimension(R.dimen.abc_action_bar_default_height_material);
floatTitleLeftMargin = getResources().getDimension(R.dimen.float_title_left_margin);
floatTitleSize = getResources().getDimension(R.dimen.float_title_size);
floatTitleSizeLarge = getResources().getDimension(R.dimen.float_title_size_large);
}
private void initView() {
listView = (ListView) findViewById(R.id.lv_main);
floatTitle = (TextView) findViewById(R.id.tv_main_title);
toolbar = (Toolbar) findViewById(R.id.tb_main);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(
true
);
}
private void initListView() {
List<String> data =
new
ArrayList<>();
for
(int i = 0; i < 40; i++) {
data.add(String.valueOf(i));
}
ArrayAdapter<String> adapter =
new
ArrayAdapter<>(
this
, android.R.layout.activity_list_item, android.R.id.text1, data);
listView.setAdapter(adapter);
}
private void initListViewHeader() {
View headerContainer = LayoutInflater.from(
this
).inflate(R.layout.header, listView,
false
);
headerBg = (ImageView) headerContainer.findViewById(R.id.img_header_bg);
listView.addHeaderView(headerContainer);
}
private void initEvent() {
listView.setOnScrollListener(
this
);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super
.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_main, menu);
return
true
;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//Y轴偏移量
float scrollY = getScrollY(view);
//变化率
float headerBarOffsetY = headerHeight - minHeaderHeight;
//Toolbar与header高度的差值
float offset = 1 - Math.max((headerBarOffsetY - scrollY) / headerBarOffsetY, 0f);
//Toolbar背景色透明度
toolbar.setBackgroundColor(Color.argb((int) (offset * 255), 0, 0, 0));
//header背景图Y轴偏移
headerBg.setTranslationY(scrollY / 2);
/*** 标题文字处理 ***/
//标题文字缩放圆心(X轴)
floatTitle.setPivotX(floatTitle.getLeft() + floatTitle.getPaddingLeft());
//标题文字缩放比例
float titleScale = floatTitleSize / floatTitleSizeLarge;
//标题文字X轴偏移
floatTitle.setTranslationX(floatTitleLeftMargin * offset);
//标题文字Y轴偏移:(-缩放高度差 + 大文字与小文字高度差)/ 2 * 变化率 + Y轴滑动偏移
floatTitle.setTranslationY(
(-(floatTitle.getHeight() - minHeaderHeight) +
//-缩放高度差
floatTitle.getHeight() * (1 - titleScale))
//大文字与小文字高度差
/ 2 * offset +
(headerHeight - floatTitle.getHeight()) * (1 - offset));
//Y轴滑动偏移
//标题文字X轴缩放
floatTitle.setScaleX(1 - offset * (1 - titleScale));
//标题文字Y轴缩放
floatTitle.setScaleY(1 - offset * (1 - titleScale));
//判断标题文字的显示
if
(scrollY > headerBarOffsetY) {
toolbar.setTitle(getResources().getString(R.string.toolbar_title));
floatTitle.setVisibility(View.GONE);
}
else
{
toolbar.setTitle(
""
);
floatTitle.setVisibility(View.VISIBLE);
}
}
/**
* 得到ListView在Y轴上的偏移
*/
public float getScrollY(AbsListView view) {
View c = view.getChildAt(0);
if
(c ==
null
)
return
0;
int firstVisiblePosition = view.getFirstVisiblePosition();
int top = c.getTop();
float headerHeight = 0;
if
(firstVisiblePosition >= 1)
headerHeight =
this
.headerHeight;
return
-top + firstVisiblePosition * c.getHeight() + headerHeight;
}
}
|