在MaterialDesign中--实现文字缩放并入Toolbar的一种方法

效果不错,不过要是让title的文字在中间,然后向上滚动到toolbar的时候有水平的位移效果就更好了。

效果:

999999.gif

实现原理

  • 底层:一个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"
     xmlns:tools= "http://schemas.android.com/tools"
     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.support.v7.widget.Toolbar xmlns:app= "http://schemas.android.com/apk/res-auto"
         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;
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值