Android-MaterialDesign-实现折叠式Tool
小萌新做的几个项目没怎么涉及到一些这方面的UI设计,所以基本上就是看过,都没真正去试用过,好尴尬呀!就是琢磨要实现一个,下拉图片跟随拉动,然后按钮或者标题跟随变化消失,上拉置顶后标题显示置顶颜色,同时按钮显示的效果。
如下类似效果:
image image<figcaption style="margin-top: 0.66667em; padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">上拉标题栏逐渐显示朋友圈,同时颜色加深</figcaption>
然后开发交流群就很热心的啦...
image然后就大概知道了AppBarLayout | Android Developers、CollapsingToolbarLayout | Android Developers、Toolbar | Android Developers 。当然了解实践过程中发现还得配合CoordinatorLayout | Android Developers方可实现相关的效果。
如果单纯的看官方文档东西还是多,而且像我发的这些链接都是相关方法,属性的介绍。api文档部分没什么demo啥的,比较少,之前学约束布局的时候倒是有的哟。 可能小萌新为了快速入手,就尽快的看相关网友的文章,github上的一些demo案例。
这个官方文档也有很多例子示例 | Android Developers 都在github上面,不太会搜呀!哈哈。。。
对MD了解各大概,对上面效果有个认识,就可以开始入手自己尝试一下。小萌新自然就从想控件入手,比如了解下Toolbar-v7兼容库中的,然后了解下CollapsingToolbarLayout -md库的可伸缩toolbar布局控件,从字面意思就大概知道,这是一个Toolbar用的外层控件,哟嘿!再然后AppBarLayout-把其所有子元素当做一个AppBar来使用。前面两个控件配合实现折叠toolbar,这个就负责布局就好了,保证作为一个整体,作为一个Appbar来使用!再接着还需要CoordinatorLayout - 它包含了AppBarLayout子控件和xx子控件,xx子控件可以是RecyclerView、NestedScrollView、ScrollView等可滑动控件,这样当我们上拉下拉这些控件的时候能和toolbar一起联动!
小萌新一开始挺迷茫的,就是你知道某个控件后,发现不知道怎么用。看api其实也能看到一些层级关系:
比如CollapsingToolbarLayout | Android Developers
CollapsingToolbarLayout is a wrapper for Toolbar which implements a collapsing app bar.
It is designed to be used as a direct child of a AppBarLayout.
CollapsingToolbarLayout contains the following features:
表达就是说CollapsingToolbarLayout是toolbar的一个容器,设计用于AppBarLayout的一个子控件。可能仔细琢磨下,貌似大概知道应该怎么用,哈哈。。 但是我觉得看看官方demo还是比较好,不然确实快速入手蛮困难的。
小萌新我直接看的网友的分享,我觉得2016人家就用了,而且分析的还可以实现折叠式Toolbar:CollapsingToolbarLayout 使用完全解析 自己都有点惭愧!
另外就是说如果要实现效果还得CoordinatorLayout | Android Developers 的辅助才行,这个东东涉及一个CoordinatorLayout.Behavior | Android Developers的概念,后面要专门学习下这块的知识。 因为之后你可能用CoordinatorLayout去搭配其他控件做其他效果,所以你需要去掌握这个控件以及相关layout_behavior的一些个概念。 这里就抛砖引玉一下,至少有个大体的深入学习的框框先定下来。
然后看下小萌新尝试的效果,针对网上的案例做了一些其他效果的实践
image控制了下ImageView的缩放,位移,以及ImageView上的图片的缩放效果(就是setImageMatrix的简单使用- 注意前提是android:scaleType="matrix")。
1. 实现关键点就是:AppBarLayout的addOnOffsetChangedListener的AppBarLayout.OnOffsetChangedListener回调,这个就是我们处理缩放、位移的地方了啦!注意点:而且像Image的位移,那个ImageView是需要放置到CoordinatorLayout之外,否则你位移的距离是会被布局限制的,就不能做全局位移了。
1.1 另外一个注意点就是:你的界面的theme不能带标题了有,需要去掉哟!我一般都有一个这样的主题,所有的界面都会设置这个。
image image1.2 其实如果你想先看效果,可以不用管addOnOffsetChangedListener回调的处理也行。那样标题栏和里面的Image也会跟随CoordinatorLayout上拉下拉产生对应的效果。不过我们想额外再控制点其他控件,以便产生更多的效果。
1.3 关于Toolbar、CollapsingToolbarLayout的一些代码设置,我们可以通过官方api有所了解,如果吃不准的话,就可以参考网上的资料。
像setTitle这些,还是比较好理解。只是小萌新不知道如何使用,只能尝试了吧?
image再附上上图完成之前效果的一些代码设置:
///< 工具栏
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(false); ///< 左上角返回图标 - false不显示
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed(); ///< 退出
}
});
//使用CollapsingToolbarLayout必须把title设置到CollapsingToolbarLayout上,设置到Toolbar上则不会显示
CollapsingToolbarLayout mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_layout);
mCollapsingToolbarLayout.setTitle("哇咔咔");
//通过CollapsingToolbarLayout修改字体颜色
mCollapsingToolbarLayout.setExpandedTitleColor(Color.WHITE);//设置还没收缩时状态下字体颜色
mCollapsingToolbarLayout.setCollapsedTitleTextColor(Color.BLACK);//设置收缩后Toolbar上字体的颜色
2. 直接来布局 activity_collapsing_toolbar_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.CollapsingToolbarLayoutActivity">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/collapsing_appbar_layout"
android:layout_width="match_parent"
android:layout_height="256dp"
android:fitsSystemWindows="true">
<!--enterAlways exitUntilCollapsed enterAlwaysCollapsed-->
<!--app:contentScrim="#30469b" - 当Toolbar收缩到一定程度时的所展现的主体颜色-->
<!--app:expandedTitleMarginStart - 展开时距离左边的距离-->
<!--app:layout_scrollFlags="scroll"所有想要滑动的控件都要设置这个标志位-->
<!-- layout_scrollFlags="exitUntilCollapsed" 向上滑动时收缩当前View。但view可以被固定在顶部-->
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="#30469b"
app:expandedTitleMarginStart="148dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/collapsing_toolbarIv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
android:src="@drawable/timg2"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7" />
<!--pin parallax-->
<!--pin:有该标志位的View在页面滚动的过程中会一直停留在顶部-->
<!--parallax:有该标志位的View表示能和页面同时滚动-->
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorAccent"
app:layout_collapseMode="pin">
<ImageView
android:id="@+id/toolbar_rightIv"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="right"
android:src="@mipmap/ic_launcher" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> <!--为滑动控件设置Behavior,这样上面的控件才能做出相应改变 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/item_card" />
<include layout="@layout/item_card" />
<include layout="@layout/item_card" />
<include layout="@layout/item_card" />
<include layout="@layout/item_card" />
<include layout="@layout/item_card" />
<include layout="@layout/item_card" />
<include layout="@layout/item_card" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/toolbar_right2Iv"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="left"
android:src="@mipmap/ic_launcher" />
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
item_card.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:background="@color/colorPrimary" />
</LinearLayout>
2.1 然后上代码吧CollapsingToolbarLayoutActivity.java
package com.example;
import android.graphics.Color;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
import com.example.hl.ViewTool;
import com.example.lieyun_android.myapplication.R;
public class CollapsingToolbarLayoutActivity extends AppCompatActivity {
private ImageView rightIv, getRight2Iv, toolbarIv;
private int initHeight;
private int toolbarHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collapsing_toolbar_layout);
rightIv = (ImageView) findViewById(R.id.toolbar_rightIv);
getRight2Iv = (ImageView) findViewById(R.id.toolbar_right2Iv);
toolbarIv = (ImageView) findViewById(R.id.collapsing_toolbarIv);
rightIv.post(new Runnable() {
@Override
public void run() {
//int width = rightIv.getMeasuredWidth();
initHeight = rightIv.getMeasuredHeight();
}
});
// Calculate ActionBar height
TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
toolbarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
}
///< AppBar高度
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.collapsing_appbar_layout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
Log.e("test", "verticalOffset=" + verticalOffset);
///< 左上角按钮做位移,注意为0的情况就间接的做消失处理
getRight2Iv.setTranslationY(-verticalOffset == 0.0f ? -200 : -verticalOffset);
///< 偏移量超过了右上角按钮高度就返回,不允许反向放大,下面有个比例scale
if (-verticalOffset > initHeight){
return;
}
float scale = (-verticalOffset) / (float)initHeight;
Log.e("test", "scale=" + scale);
rightIv.setScaleX(scale);
rightIv.setScaleY(scale);
float scaleR;
if (scale > 0.0f){
scaleR = (1.0f - scale);
Log.e("test", "scale2=" + scaleR);
if (scaleR < 0.5f){
return;
}
}else{
scaleR = 1.0f - scale;
}
//toolbarIv.setScaleX(scaleR);
//toolbarIv.setScaleY(scaleR);
///< 负责处理ImageView的drawable的缩放效果,需要Matrix哟。。这个有时间要深入。
ViewTool.scaleImageViewDrawable(toolbarIv, scaleR);
}
});
///< 工具栏
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(false); ///< 左上角返回图标 false - 不显示
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
//使用CollapsingToolbarLayout必须把title设置到CollapsingToolbarLayout上,设置到Toolbar上则不会显示
CollapsingToolbarLayout mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_layout);
mCollapsingToolbarLayout.setTitle("哇咔咔");
//通过CollapsingToolbarLayout修改字体颜色
mCollapsingToolbarLayout.setExpandedTitleColor(Color.WHITE);//设置还没收缩时状态下字体颜色
mCollapsingToolbarLayout.setCollapsedTitleTextColor(Color.BLACK);//设置收缩后Toolbar上字体的颜色
}
}
工具类 ViewTool.java
package com.example.hl;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.widget.ImageView;
/**
* Created by hl on 2018/3/20.
*/
public class ViewTool {
public static void scaleImageViewDrawable(ImageView imageView, float scale){
Drawable drawable = imageView.getDrawable();
if (null == drawable){
return;
}
int imageWidth = drawable.getIntrinsicWidth();// 图片的宽度
int imageHeight = drawable.getIntrinsicHeight();// 图片的高度
int width = imageView.getWidth();// 控件的宽度
int height = imageView.getHeight();// 控件的高度
int dx = width / 2 - imageWidth / 2;
int dy = height / 2 - imageHeight / 2;
Matrix mScaleMatrix = new Matrix();
mScaleMatrix.postTranslate(dx, dy);
Log.e("test", "postScale=" + scale);
mScaleMatrix.postScale(scale*2.5f/3, scale*2.5f/3, width / 2, height / 2);
imageView.setImageMatrix(mScaleMatrix);
}
}
基本就ok了。。缺的图片补补就好了。时间有点赶。具体效果还可以调。而且要想搞得更好,肯定还是需要再深入一些其他知识的(什么behavior啥的,其他md的控件啥的....),这篇就算是初识。。小萌新要接触,学习,实践的东西还好多呀。。我的天。。。