您的位置:首页 > 移动开发 > Android开发

android新特性:使用CollapsingToolbarLayout实现折叠效果及问题解决

2017-04-17 14:48 1316 查看
CollapsingToolbarLayout作用是提供了一个可以折叠的Toolbar,它继承至FrameLayout,给它设置layout_scrollFlags就可以实现折叠效果!

效果展示:



20170209104448181.gif

引入相对使用的库
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0'
compile 'com.android.support:support-v4:23.3.0'

compile 'com.jakewharton:butterknife:7.0.1'
//沉浸状态栏
compile 'com.jaeger.statusbaruitl:library:1.1.1'
//glide图片加载
compile 'jp.wasabeef:glide-transformations:2.0.1'

首先查看布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:id="@+id/coordinator_Layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.hnshangyu.coordinatorlayout.MainActivity">

<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"
android:layout_width="match_parent"
android:layout_height="300dp"
app:collapsedTitleTextAppearance="@style/ToolBarTitleText"
app:contentScrim="#46a8ba"
app:expandedTitleMarginEnd="48dp"
app:expandedTitleMarginStart="48dp"
app:expandedTitleTextAppearance="@style/transparentText"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<!--设置layout_scrollFlags保证CollapsingToolbarLayout能滚动-->
<!--app:layout_scrollFlags="scroll|exitUntilCollapsed"-->

<LinearLayout
android:id="@+id/head_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_collapseMode="pin"
app:layout_collapseParallaxMultiplier="0.7">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:padding="20dp">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="黄晓果"
android:textColor="#ffffff"
android:textSize="16sp"
android:textStyle="bold" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:lineSpacingMultiplier="1.3"
android:text="我很喜欢你,像你妈打你,没有道理;\n像放出的屁,身不由己。"
android:textColor="#ffffff"
android:textSize="13sp"
android:textStyle="bold" />
</LinearLayout>

<ImageView
android:id="@+id/head_iv"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:scaleType="centerCrop" />
</RelativeLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="40dp"
android:ellipsize="end"
android:lineSpacingMultiplier="1.3"
android:maxLines="2"
android:text="萌逼的脸是来亲的,帅逼的脸是用来看的,逗逼的脸是用来笑的,傻逼的脸是用来哭的,偏偏就你的脸是用来踢的。"
android:textColor="#ffffff"
android:textSize="12sp" />

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:padding="20dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="40dp"
android:ellipsize="end"
android:lineSpacingMultiplier="1.3"
android:maxLines="2"
android:text="今天的你对我爱搭不理,\n明天的我还来找你。"
android:textColor="#ffffff"
android:textSize="12sp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@drawable/setting_bg"
android:paddingBottom="3dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:paddingTop="3dp"
android:text="设置"
android:textColor="#ffffff"
android:textSize="12sp" />
</RelativeLayout>
</LinearLayout>
<!--Toolbar放在下面不然会被挡住-->
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.CollapsingToolbarLayout>

<android.support.design.widget.TabLayout
android:id="@+id/toolbar_tab"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_gravity="bottom"
android:background="#ffffff"
android:fillViewport="false"
app:layout_scrollFlags="scroll"
app:tabIndicatorColor="#0835f8"
app:tabIndicatorHeight="2.0dp"
app:tabSelectedTextColor="#0835f8"
app:tabTextColor="#151515">

<!--指示器颜色-->
<!-- app:tabIndicatorColor="#0835f8"-->

<!--tab条目中字体颜色-->
<!--app:tabSelectedTextColor="#0835f8"-->

<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/tab_selector" />
<!--布局选择器-->
<!--android:icon="@drawable/tab_selector"-->
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="头条" />

<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="社交" />

<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="直播" />

<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="约吗" />

</android.support.design.widget.TabLayout>

</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<android.support.v4.view.ViewPager
android:id="@+id/main_vp_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.v4.widget.NestedScrollView>
<!--在CoordinatorLayout中只要是能滑动控件的都需要设置layout_behavior-->
<!--app:layout_behavior="@string/appbar_scrolling_view_behavior"-->
</android.support.design.widget.CoordinatorLayout>

内部特殊的属性都有相对注释:

我们在CollapsingToolbarLayout中设置了一个LinearLayout和一个Toolbar。
并把这个CollapsingToolbarLayout放到AppBarLayout中作为一个整体。

1、在CollapsingToolbarLayout中:

我们设置了layout_scrollFlags:关于它的值我这里再说一下:
scroll - 想滚动就必须设置这个。

enterAlways - 实现quick return效果, 当向下移动时,立即显示View(比如Toolbar)。

exitUntilCollapsed - 向上滚动时收缩View,但可以固定Toolbar一直在上面。

enterAlwaysCollapsed - 当你的View已经设置minHeight属性又使用此标志时,
你的View只能以最小高度进入,只有当滚动视图到达顶部时才扩大到完整高度。

其中还设置了一些属性,简要说明一下:

contentScrim - 设置当完全CollapsingToolbarLayout折叠(收缩)后的背景颜色。

expandedTitleMarginStart - 设置扩张时候(还没有收缩时)title向左填充的距离。

layout_collapseMode (折叠模式) - 有两个值:

pin -  设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上。

parallax - 设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,
实现视差滚动效果,通常和layout_collapseParallaxMultiplier(设置视差因子)搭配使用。

layout_collapseParallaxMultiplier(视差因子) - 设置视差滚动因子,值为:0~1。

这里使用到了部分样式:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<style name="transparentText" parent="TextAppearance.AppCompat.Small">
<item name="android:textColor">#00000000</item>
</style>

<style name="ToolBarTitleText" parent="TextAppearance.AppCompat.Medium">
<item name="android:textColor">#ffffffff</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>

</style>

然后就是MainActivity中的代码设置了:
package cn.hnshangyu.coordinatorlayout;

import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import com.jaeger.library.StatusBarUtil;

import butterknife.Bind;
import butterknife.ButterKnife;
import cn.hnshangyu.coordinatorlayout.adapter.ViewPagerAdapter;
import jp.wasabeef.glide.transformations.BlurTransformation;
import jp.wasabeef.glide.transformations.RoundedCornersTransformation;

public class MainActivity extends AppCompatActivity {

/**
* ScrollView上半部分
*/
@Bind(R.id.toolbar)
Toolbar toolbar;
/**
* 头像
*/
@Bind(R.id.head_iv)
ImageView headIv;
/**
* CollapsingToolbarLayout内部显示内容部分
*/
@Bind(R.id.head_layout)
LinearLayout headLayout;
/**
* tab分类条目
*/
@Bind(R.id.toolbar_tab)
TabLayout toolbarTab;

@Bind(R.id.app_bar_layout)
AppBarLayout appBarLayout;
/**
* 折叠部分
*/
@Bind(R.id.collapsingToolbarLayout)
CollapsingToolbarLayout collapsingToolbarLayout;
/**
* ViewPager
*/
@Bind(R.id.main_vp_container)
ViewPager mViewPager;
/**
* ScrollView
*/
@Bind(R.id.nsv)
NestedScrollView nsv;
/**
* 整个布局
*/
@Bind(R.id.coordinator_Layout)
CoordinatorLayout coordinatorLayout;

private ViewPagerAdapter myPagerAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);

//用toolBar替换ActionBar
setToolBarReplaceActionBar();

//把title设置到CollapsingToolbarLayout上
setTitleToCollapsingToolbarLayout();

// 给viewpager设置适配器
setViewPagerAdapter();

//tablayout和viewpager建立联系
setTabBindViewPager();

//设置毛玻璃效果和沉浸状态栏
loadBlurAndSetStatusBar();

//设置头像
Glide.with(this).load(R.mipmap.bg).bitmapTransform(new RoundedCornersTransformation(this,
90, 0)).into(headIv);
}

/**
* 用toolBar替换ActionBar
*/
private void setToolBarReplaceActionBar() {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "返回", Toast.LENGTH_LONG).show();
// onBackPressed();//结束程序
}
});
}

/**
* 使用CollapsingToolbarLayout必须把title设置到CollapsingToolbarLayout上,
* 设置到Toolbar上则不会显示
*/
private void setTitleToCollapsingToolbarLayout() {
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (verticalOffset <= -headLayout.getHeight() / 2) {
collapsingToolbarLayout.setTitle("黄晓果");
//使用下面两个CollapsingToolbarLayout的方法设置展开透明->折叠时你想要的颜色
collapsingToolbarLayout.setExpandedTitleColor(getResources().getColor(android.R.color.transparent));
collapsingToolbarLayout.setCollapsedTitleTextColor(getResources().getColor(R.color.colorAccent));
} else {
collapsingToolbarLayout.setTitle("");
}
}
});
}

/**
* 给viewpager设置适配器
*/
private void setViewPagerAdapter() {
myPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), this);
mViewPager.setAdapter(myPagerAdapter);
}

/**
* tablayout和viewpager建立联系
*/
private void setTabBindViewPager() {
//tablayout和viewpager建立联系方式一:tab与viewpager之间的相互绑定
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener
(toolbarTab));
toolbarTab.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener
(mViewPager));

//tablayout和viewpager建立联系方式二: 使用此方法Tablayout中的TabItem设置icon无效
// (android:icon="@drawable/tab_selector" )只能使用 android:text="分享"
//  toolbarTab.setupWithViewPager(mViewPager);
}

/**
* 设置毛玻璃效果和沉浸状态栏
*/
private void loadBlurAndSetStatusBar() {
//目的是让状态栏半透明
//         StatusBarUtil.setTranslucent(MainActivity.this, StatusBarUtil.DEFAULT_STATUS_BAR_ALPHA);
//目的是让状态栏全透明
StatusBarUtil.setTransparent(MainActivity.this);

Glide.with(this).load(R.mipmap.bg).bitmapTransform(new BlurTransformation(this, 100))
.into(new SimpleTarget<GlideDrawable>() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super
GlideDrawable> glideAnimation) {
headLayout.setBackground(resource);
coordinatorLayout.setBackground(resource);
}
});

Glide.with(this).load(R.mipmap.bg).bitmapTransform(new BlurTransformation(this, 100))
.into(new SimpleTarget<GlideDrawable>() {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super
GlideDrawable> glideAnimation) {
collapsingToolbarLayout.setContentScrim(resource);
}
});
}

//在ActionBar设置条目
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
String msg = "";
switch (item.getItemId()) {
case R.id.webview:
msg += "博客跳转";
break;
case R.id.weibo:
msg += "微博跳转";
break;
case R.id.action_settings:
msg += "设置";
break;
}
if (!msg.equals("")) {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}

}

代码内部有详细注释

【注】:使用CollapsingToolbarLayout时必须把title设置到CollapsingToolbarLayout上,设置到Toolbar上不会显示。
即:
mCollapsingToolbarLayout.setTitle(" ");

该变title的字体颜色:

扩张时候的title颜色:mCollapsingToolbarLayout.setExpandedTitleColor();

收缩后在Toolbar上显示时的title的颜色:mCollapsingToolbarLayout.setCollapsedTitleTextColor();

这个颜色的过度变化其实CollapsingToolbarLayout已经帮我们做好,它会自动的过度

ViewPagerAdapter:
package cn.hnshangyu.coordinatorlayout.adapter;

import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import cn.hnshangyu.coordinatorlayout.fragment.PageFragment;

public class ViewPagerAdapter extends FragmentPagerAdapter {

final int PAGE_COUNT = 5;
private String tabTitles[] = new String[]{"", "头条", "社交", "直播", "约吗"};
private Context context;

public ViewPagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}

@Override
public Fragment getItem(int position) {
return PageFragment.newInstance(position + 1);
}

@Override
public int getCount() {
return PAGE_COUNT;
}

@Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
}

PageFragment:
package cn.hnshangyu.coordinatorlayout.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

import butterknife.Bind;
import butterknife.ButterKnife;
import cn.hnshangyu.coordinatorlayout.R;
import cn.hnshangyu.coordinatorlayout.adapter.MyAdapter;

public class PageFragment extends Fragment {
public static final String ARG_PAGE = "PAGE_NUM";
@Bind(R.id.recyclerView)
RecyclerView recyclerView;
private int mPage;

public static PageFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
PageFragment pageFragment = new PageFragment();
pageFragment.setArguments(args);
return pageFragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARG_PAGE);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page, null);
ButterKnife.bind(this, view);
// 创建一个线性布局管理器

LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());

// 设置布局管理器

recyclerView.setLayoutManager(layoutManager);

List<String> list = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
list.add("黄晓果" + i);
}
recyclerView.setAdapter(new MyAdapter(list));

return view;
}

@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
}

MyAdapter:
package cn.hnshangyu.coordinatorlayout.adapter;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
// 数据集
private List<String> mDataset;

public MyAdapter(List<String> dataset) {
super();
mDataset = dataset;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

// 创建一个View,简单起见直接使用系统提供的布局,就是一个TextView

View view = View.inflate(viewGroup.getContext(), android.R.layout.simple_list_item_1, null);

return new ViewHolder(view);

}

@Override
public void onBindViewHolder(ViewHolder holder, int i) {

// 绑定数据到ViewHolder上

holder.mTextView.setText(mDataset.get(i));

}

@Override
public int getItemCount() {

return mDataset.size();

}

class ViewHolder extends RecyclerView.ViewHolder {

public TextView mTextView;

public ViewHolder(View itemView) {

super(itemView);

mTextView = (TextView) itemView;

}

}

}

menu_main:
<?xml version="1.0" encoding="utf-8"?>
<menu 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"
tools:context=".MainActivity">

<item
android:id="@+id/webview"
android:icon="@mipmap/icon_blog"
android:orderInCategory="80"
android:title="web"
app:showAsAction="ifRoom" />

<item
android:id="@+id/weibo"
android:icon="@mipmap/icon_weibo"
android:orderInCategory="90"
android:title="weibo"
app:showAsAction="ifRoom" />

<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="设置"
app:showAsAction="never" />
</menu>


问题一:
异常信息:

Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.

问题原因:

当在activity中调用了setSupportActionBar(toolbar);



20170209111040427.png

同时,AndroidManifest.xml 对应的Activity标签的android:theme为:

android:theme="@style/AppTheme" >




20170209111137016.png

且,style资源文件中的parent为

parent="Theme.AppCompat.Light.DarkActionBar




20170209111203412.png

就会报这个异常。

问题分析:

Using Theme.AppCompat.Light tells Android that you want the framework to provide an ActionBar for you. However, you are creating your own ActionBar (a Toolbar), so you are giving the framework mixed signals as to where you want the ActionBar to come from.

解决方法:

1、在style配置文件中加上

<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>

或者,将parent改为

parent="Theme.AppCompat.Light.NoActionBar"

2、在AndroidManifest.xml 对应的Activity标签的android:theme引用该style中的修改的主题

问题二:
问题:

当成功运行程序后如果在6.0及以上的机子上运行会出现顶部状态栏显示系统颜色,这里是   coordinatorLayout.setBackground(resource);这行代码无效的情况

解决方式:

将编译版本,修改到23且 compile 'com.jaeger.statusbaruitl:library:1.1.1'版本为1.1.1,如果设置为现在最高版本1.3.5会出现,编译不通过!

compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "cn.hnshangyu.coordinatorlayout"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
renderscriptTargetApi 19
renderscriptSupportModeEnabled true
}

Demo下载地址:http://download.csdn.net/download/huangxiaoguo1/9750621

好了,到这里就结束了,欢迎各位指教.......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐