android-view(2)

上一篇学习了 view 是怎样被组织显示的,这一次主要是学习怎样设计自己的 ContentView,首先我们要知道的知识有:android 的坐标系、常用的布局、LayoutParams 参数。

1.认识 android 的坐标系
就我所知,android 中主要有屏幕坐标系和 view 的坐标系两个概念,看下图:
这里写图片描述
上图左边的是屏幕坐标系,上一篇我们提及到的 DecorView(包括一个状态栏、内容区和导航栏)占据了整个屏幕,所以 DecorView 的坐标系,就等价于屏幕坐标系了,除了 DecorView 这个特殊的 View,其他 View 都是相对于父布局的,如上图左边,View 的坐标系是相对于其父布局的,要确定 View 的大小和位置,其实只要确定 View 的左上角和右下角的坐标即可,因为其实所有 View 都是矩形。 根据 DecorView 的构成,我们易知 ContentView,也就是 activity 对应的“根布局”的父布局就是 ContentFrameLayout,所以 ContentView 的坐标系的 Y 相对于屏幕坐标系的 Y 是要下移一个状态栏和标题栏的高度的。

在 View 中分别有四个属性:left、top、right、bottom , 分别代表左上角、右下角的横坐标、纵坐标,可以通过 left = view.getLfet() 获得,以此类推。值得注意的是,在 view 中也有四个这样的属性:x、y、translationX、transltionY。其中 x , y 代表 view 的左上角的位置(这个才是显示的位置),他们的关系如下:

x = left + translationX;
y = right + translationY;

在默认情况下 translationX 和 translationY 均是 0,即 x = left ,y = right ,因为此时 View 没有被移动,如果移动了 view , translationX 或 translationY 就不是 0 ,view 移动和 x , y 坐标变化是相对应的,x , y 才是真正确定 view 的显示位置的,这里会在 view 的滑动中进一步学习。

2.认识 LayoutParams
有了上面的坐标系,一个 view 要显示出来,如果不考虑如何绘制,最起码也要知道 view 的大小和位置,我们能不能动态的改变 view 的大小和位置呢,答案是肯定的,LayoutParams 就保存了 view 的各种参数信息,通过修改 LayoutParams 中的参数可以实现 View 的滑动。

LayoutParams 是布局参数,是 ViewGroup 的内部类,是 view 用来告知它的父布局自己需要怎样的摆放,MarginLayoutParams 是 LayoutParams 的直接子类,我们一般都是使用 MarginLayoutParams 的,获得:

MarginLayoutParams params=(MarginLayoutParams)view.getLayoutParams();

然后通过修改 MarginLayoutParams 中的参数信息,就可以得到更新 view 的属性参数信息了。

3. 常用布局
android 中的常用布局有:线性布局 LinearLayout、相对布局RelativeLayout、帧布局 FrameLayout、百分比布局 PercentRealativeLayout、PercentFrameLayout,对于这些常用布局的使用,比较简单,也没什么好说的,就记录一些自己觉得重要的属性。

属性说明可用布局
layout_gravity控制在布局中的对齐方式LinearLayout、FrameLayout
gravity控制 view 内部内容的对齐方式
layout_weight把剩余布局空间按比例分配LinearLayout

值得注意的是:在 LinearLayout 使用 layout_gravity 属性时,只作用于一个方向,如设定 orientation = “vertical”,则作用于 “horizontal” 方向,相反则反。

通过使用 layout_weight 属性可以做到以百分比来指定控件的大小,但是 layout_weight 只用于 LinearLayout ,为此 android 引入了一种全新的布局方式来解决RelativeLayout、FrameLayout 不能使用百分比确定控件大小的问题,引入的布局是百分比布局(分别继承相对布局和帧布局)。在 gradle 中添加 compile ‘com.android.support:percent:24.2.1’ 后同步一下,即可使用 PercentRealativeLayout、PercentFrameLayout。其中两个重要属性就是:app:layout_widthPercent 和 app:layout_heightPercent,控制控件占据父布局宽高的百分比。

4. material 布局与控件
1) 圆角化 CircleImageView
在 build.gradle 文件的 dependencies 闭包中添加库路径,并 Sync now 同步一下:

compile 'de.hdodenhof:circleimageview:2.1.0'
compile 'com.android.support:design:24.2.1'

同步后,就可以在 xml 文件中使用控件 CircleImageView , 使用方法和 imageView 一样。

 <de.hdodenhof.circleimageview.CircleImageView
        android:layout_centerInParent="true"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:src="@drawable/dog"/>

效果:
这里写图片描述

2)FloatingActionButton
FloatingActionButton 是悬浮按钮,使用和 Button 一样,需要注意的是有几个重要属性:

属性说明
elevation按钮的立体高度值,单位为 dp,值越大,投影效果越深
layout_anchor锚点,值为 id ,选择悬浮在哪个布局中
layout_anchorGravity悬浮在布局中的哪个方位

(layout_anchor 和 layout_anchorGravity 属性在 CoordinatorLayout 中才适用)

<android.support.design.widget.FloatingActionButton
        android:id="@+id/floating_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:elevation="80dp"
        app:layout_anchor ="@id/linear_layout"
        app:layout_anchorGravity="center"
        android:src="@drawable/share"/>

效果:其中那个框框就是一个 LinearLayout ,根据效果图就容易理解锚点属性了。
这里写图片描述

4)CoordinatorLayout 是一个加强版的 FrameLayout ,可以监听所有子控件的事件,自动帮助我们做出最为合理的响应,经常会结合 ToolBar 使用,看下面的例子:

/*
*  在一个 FrameLayout 中放置一个 FloatingActionButton 并为其设置
*  点击响应监听,在监听中使用 SnackBar 做出点击提示
*/
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floating_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:elevation="80dp"
        android:layout_margin="15dp"
        android:layout_gravity="bottom|end"
        android:src="@drawable/share"/>
</FrameLayout>

效果:
这里写图片描述

/*
*  在一个 CoordinatorLayout 中放置一个 FloatingActionButton 并为其
*  设置点击响应监听,在监听中使用 SnackBar 做出点击提示
*/
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floating_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:elevation="80dp"
        android:layout_margin="15dp"
        android:layout_gravity="bottom|end"
        android:src="@drawable/share"/>
</android.support.design.widget.CoordinatorLayout>

效果:
这里写图片描述

通过比较效果可以看出 CoordinatorLayout 对其子控件做了优化响应

5)CardView 是一个 FrameLayout , 提供了圆角和阴影效果,对应两个属性分别是: elevation 和 cardCornerRadius

 <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_margin="20dp"
        app:elevation="10dp"
        app:cardCornerRadius="20dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="hello word"/>

    </android.support.v7.widget.CardView>

效果:
这里写图片描述

5)TextInputLayout
先看看介绍:
这里写图片描述
TextInputLayout 是一个 LinearLayout 布局,可以包裹一个 EditText及其子类(如 TextInputEditText ) ,主要功能有如下:
a.在用户输入文本覆盖默认文本时,会把默认文本标签移动到上方。
b.支持通过 setErrorEnabled(boolean) 和setError(CharSequence) 显示错误,并通过setCounterEnabled(boolean) 显示一个字符计数器。
c.通过 setPasswordVisibilityToggleEnabled(boolean) 和相关属性的设定,可以支持密码可见性切换。

我们可以通过在 xml 设定属性或者对应的方法设定属性就可以达到 a,b,c 的效果,结合sector 标签的 drawable 资源使用,效果更佳,下面记录一些常用的属性。

属性对应方法说明
counterEnabledsetCounterEnabled(boolean)是否开启字符计数器
counterMaxLengthsetMaxLength(int)计数器计算的最大字符数
errorEnablesetErrorEnabled(boolean)是否开启错误提示
errorTextAppearancesetError(cahrSequeue)错误提示内容
hintTextAppearancesetHintTextAppearance(int)设置提示语的风格
passwordToggleEnabledsetPasswordVisibilityToggleEnabled(boolean)是否开启密码可见开关,注意设置 editText 的 inputType 属性
passwordToggleDrawablesetPasswordVisibilityToggleDrawable(Drawable)设置密码可见开关的图标,可以引用一个 sector drawable 资源
passwordToggleTintsetPasswordVisibilityToggleTintList(ColorStateList)控制密码可见开关图标的颜色,可以引用一个 sector color 资源
//  password 部分的 xml
 <android.support.design.widget.TextInputLayout
        android:id="@+id/psw_input_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:passwordToggleTint="@color/btn_sector">

        <android.support.design.widget.TextInputEditText
            android:id="@+id/password"
            android:maxLines="1"
            android:singleLine="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textPassword"
            android:hint="password"/>
    </android.support.design.widget.TextInputLayout>

效果:
这里写图片描述 这里写图片描述

6) TabLayout
这里写图片描述
TabLayout 是一个 HorizontalScrollview ,用作导航指示器,我们可以通过 tabLayout.newTab() 方法创建一个 Tab 对象然后添加到 TabLayout 中,可以通过 setText 和 setIcon 方法设置导航标题。一般结合 ViewPager 使用,这样会自动使 ViewPager 与 Tab 联动。

简单代码如下:

<android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        app:tabIndicatorColor="@android:color/white"
        app:tabTextColor="@color/colorGray"
        app:tabSelectedTextColor="@android:color/white" />

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
public class MainActivity extends AppCompatActivity {
    private List<Fragment> fragmentList = new ArrayList<Fragment>();
    private List<String> titleList = new ArrayList<String>();
    private TabLayout mTabLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initAllView();
        ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
        viewPager.setAdapter(new MyViewPagerAdapter(getSupportFragmentManager()));
        // 给 TabLayout 布局加载 viewPager
        mTabLayout.setupWithViewPager(viewPager);

    }
    // 初始化一些 view
    private void initAllView(){
        fragmentList.add(new MyFragment());
        fragmentList.add(new MyFragment());
        fragmentList.add(new MyFragment());
        fragmentList.add(new MyFragment());
        titleList.add("tab1");
        titleList.add("tab2");
        titleList.add("tab3");
        titleList.add("tab4");
        mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
        mTabLayout.addTab(mTabLayout.newTab());
        mTabLayout.addTab(mTabLayout.newTab());
        mTabLayout.addTab(mTabLayout.newTab());
        mTabLayout.addTab(mTabLayout.newTab());
    }

    class MyViewPagerAdapter extends FragmentPagerAdapter{

        public MyViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            MyFragment fragment = (MyFragment) fragmentList.get(position);
            return fragment;
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }
        /*
        *  注意一定要重写 getPageTitle 方法,以为在这里 TabLayout 是
        *  结合 ViewPager 使用,tab 的 text 是取 PageTitle 为准的
        */
        @Override
        public CharSequence getPageTitle(int position) {
            return titleList.get(position);
        }
    }

}

效果(菜鸟还不会截动图):
这里写图片描述

需要记录的属性:
这里写图片描述

如果我们需要响应 tab 的选择事件,可以为 tabLayout 设置 TabLayout.TabLayoutOnPageChangeListener,方法如下:

/*
* This method was deprecated in API level 24.0.0. Use 
* addOnTabSelectedListener(OnTabSelectedListener) and 
* removeOnTabSelectedListener(OnTabSelectedListener).
*/
setOnTabSelectedListener(TabLayout.OnTabSelectedListener listener)

7)DrawerLayout 和 NavigationView
DrawerLayout 是一个滑动菜单布局,在布局中可以包含两个子控件,第一个子控件是屏幕主内容区,第二个控件是侧滑的导航菜单,侧滑的导航菜单一般结合 NavigationView 使用,当然也可以不使用 NavigationView。简单用法如下:

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/drawer_layout">

    <RelativeLayout
        android:id="@+id/content_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_centerInParent="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="主屏幕区内容"
            android:textSize="30sp"/>
    </RelativeLayout>

    <android.support.percent.PercentFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start">
        <android.support.design.widget.NavigationView
            app:layout_widthPercent="90%"
            app:layout_heightPercent="100%"
            android:id="@+id/navigation_view"
            app:menu="@menu/navi_menu"
            app:headerLayout="@layout/header_layout" />
    </android.support.percent.PercentFrameLayout>
</android.support.v4.widget.DrawerLayout>

上面的 xml 片段,DrawerLayout 中包含了一个 RelativeLayout 显示主屏幕内容,一个 PercentFrameLayout 显示侧滑菜单,在 PercentFrameLayout 中包裹了一个 NavigationView ,这里使用百分比布局主要是为了能够控制菜单占据屏幕的百分比。

需要注意的地方: 侧滑菜单一定要设定 android:layout_gravity 属性,表示从左侧还是有侧滑出,一般使用 start 或 end ,分别表示左侧滑出 或右侧滑出,这里的左右是取决于系统设置的语言是从左到右还是从右到左的。

NavigationView 的使用:其中有两个属性 app:menu 和 app:headerLayout 分别指定一个头布局和菜单栏,所以我们要事先准备好一个头布局和一个菜单的 xml 文件,然后通过这两个属性指定即可。

nav_menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
    <item
        android:id="@+id/message"
        android:title="我的消息"
        android:icon="@mipmap/message1"/>
    <item
        android:id="@+id/phone"
        android:title="我的电话"
        android:icon="@mipmap/phone"/>
    <item
        android:id="@+id/friends"
        android:title="我的朋友"
        android:icon="@mipmap/friends"/>
    <item
        android:id="@+id/sub_item"
        android:title="subItem">
        <menu>
            <item
                android:id="@+id/settings"
                android:title="设置"
                android:icon="@mipmap/settings"/>
            <item
                android:id="@+id/moon_style"
                android:title="夜间模式"
                android:icon="@mipmap/night"/>
            <item
                android:id="@+id/exit"
                android:title="退出"
                android:icon="@mipmap/turn_off"/>
        </menu>
    </item>
    </group>
</menu>

header_layout.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="@drawable/bg">
    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/circle_image_view"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_centerInParent="true"
        android:src="@drawable/dog"/>
    <TextView
        android:layout_marginTop="20dp"
        android:id="@+id/name_text_view"
        android:layout_below="@id/circle_image_view"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="小小莫是我"
        android:textColor="@android:color/white"
        android:textSize="25sp"/>
    <TextView
        android:layout_toRightOf="@id/name_text_view"
        android:layout_alignTop="@id/name_text_view"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:textColor="@android:color/white"
        android:text="lv.5"    android:background="@drawable/bg_rectangle_with_stroke_dash"
        />
</RelativeLayout>

那么如何给菜单项添加事件响应:

DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem item) {
            // 通过菜单项 id 识别菜单项
                drawerLayout.closeDrawer(GravityCompat.START);
                return true;
            }
        });

当你点击菜单以外的地方,会自动滑动隐藏菜单,我们也可以通过代码来打开和关闭菜单:

// 注意这里穿进去的参数要和 xml 中的 layout_gravity 值一致
drawerLayout.closeDrawer(GravityCompat.START);
drawerLayout.openDrawer(GravityCompat.START);

效果(菜鸟还不会截动图):
这里写图片描述 这里写图片描述

8) CoordinatorLayout 、ToolBar 、AppBarLayout
工具栏 ToolBar 是用来代替 ActionBar 的,它具有 ActionBar 功能,此外也有 MaterialDesign 效果,简单用法如下:

<FrameLayout
        android:id="@+id/content_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
            <android.support.v7.widget.Toolbar
                android:id="@+id/tool_bar"
                android:layout_width="match_parent"
                android:background="#DC143C"
                android:layout_height="?attr/actionBarSize"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </FrameLayout>

上面 xml 片段,在 FrameLayout 中放置一个 Toolbar 和 RecyclerView , 由于是 FrameLayout ,所以 RecyclerView 会覆盖 Toolbar。
这里写图片描述

为了解决这个 bug ,常规做法是让 RecyclerView 下移一个工具栏的高度,我们也可以对 Toolbar 嵌套一个 AppBarLayout ,如下:

<FrameLayout
        android:id="@+id/content_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#DC143C"
            android:paddingTop="25dp">

            <android.support.v7.widget.Toolbar
                android:id="@+id/tool_bar"
                android:layout_width="match_parent"
                android:background="#DC143C"
                android:layout_height="?attr/actionBarSize"/>

        </android.support.design.widget.AppBarLayout>
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </FrameLayout>

这里写图片描述

上面的是 xml 中的定义,在代码区我们也要做相应的工作,在使用工具栏时,我们首先需要隐藏原来的 AcitonBar,可以在 xml 中修改 Style:

// 这里是直接继承 Theme.AppCompat.Light.NoActionBar
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

然后在 onCreate 方法中:

// 告知使用 Toolbar 代替 ActionBar
Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
// 这里可以设定 toolBar 左侧导航图标按钮,我们在onOptionsItemSelected 
// 方法中响应点击左侧导航图标,其按钮 id 为 android.R.id.home
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
// 图标默认为左侧箭头,这里可以设定自己的图标
actionBar.setHomeAsUpIndicator(R.mipmap.home);

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home :
                mDrawerLayout.openDrawer(GravityCompat.START);
                break;
        }
        return true;
    }

我们提及到过 CoordinatorLayout ,它是一个加强版的 FrameLayout,可以监听所有子控件的事件,自动帮助我们做出最为合理的响应,既然这样我们看看把 CoordinatorLayout 代换成 FrameLayout 试试看:

<android.support.design.widget.CoordinatorLayout
        android:id="@+id/content_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/tool_bar"
                android:layout_width="match_parent"
                android:background="#DC143C"
                android:paddingTop="25dp"
                android:layout_height="wrap_content"
                app:layout_scrollFlags="enterAlways|snap|scroll" />

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

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
          app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

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

看上面的 xml 片段,在 ToolBar 中添加 app:layout_scrollFlags 属性 ,在 RecyclerView 中添加 app:layout_behavior=”@string/appbar_scrolling_view_behavior。
看效果(截下的是mp4,在线转为gif就这样了,比较模糊,意思意思就好了):
这里写图片描述
我们可以看到,toolbar 与 RecyclerView 的滚动同步了,当向上滚动时候,toolbar会一同向上滚动,至隐藏,当向下滚动时,toolbar 又显示了。ToolBar 中app:layout_scrollFlags 属性 和 RecyclerView 中app:layout_behavior 属性能够使他们联动。

app:layout_scrollFlags 值说明
scrool向上滚动时一同滚动
snaptoolBar 没有完全显示或隐藏时,根据滑动距离做出选择
enterAlways一发现向下滚动则显示toolBar
exitUntilCollapsed滚动折叠完成后保留显示在界面,在CollapsingToolBarLayout 中即将使用

9)CollapsingToolBarLayout
上面我们看到的 toolbar 的 Material 效果就是可以与其他控件联动,那可不可以设计一个更高级的 toolbar , 是可以的。CollapsingToolBarLayout 是一个 FrameLayout , 它可以代表一个高级的标题栏,但是它必须是 AppBarLayout 的直接子布局,而 AppBarLayout 又必须是 CoordinatorLayout 的子布局。一般会用 CollapsingToolBarLayout 来包裹一个 Toolbar ,但不是必须的。看下面的 xml 片段:

 <android.support.design.widget.CoordinatorLayout
        android:id="@+id/content_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapse_tool_bar_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:contentScrim="#DC143C"
                app:layout_scrollFlags="scroll|exitUntilCollapsed"
                app:title="小小莫是我">

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scaleType="centerCrop"
                    android:src="@drawable/bg"
                    app:layout_collapseMode="parallax"
                    />

                <android.support.v7.widget.Toolbar
                    android:id="@+id/tool_bar"
                    android:layout_width="match_parent"
                    android:paddingTop="25dp"
                    android:layout_height="85dp"
   android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                    android:popupTheme="@style/Theme.AppCompat.Light"
                    app:layout_collapseMode="pin" />

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

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

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
           app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    </android.support.design.widget.CoordinatorLayout>

效果:
这里写图片描述

我们可以看到 CollapsingToolbarLayout 就是我们定制的标题栏,因为标题栏,不再是 ToolBar 了,所以相应的我们要把 app:layout_scrollFlags 属性上移一层至 CollapsingToolbarLayout,使其与 RecyclerView 联动。在 CollapsingToolbarLayout 中,可以看到有一个 imageView 和 toolBar ,其中有一个 app:layout_collapseMode 属性,它的作用是指定当前控件在 CollapsingToolbarLayout 折叠中的折叠模式,parallax 指在折叠中产生错位偏移, pin 指 位置始终保持不变。还有 app:contentScrim 属性,它是指定在完成折叠后标题栏的背景色。注意,CollapsingToolbarLayout 是一个 FrameLayout , 我们可以在其中添加更多的控件,ToolBar 其实也是一个ViewGroup , 我们也可以在其中添加控件。

CollapsingToolbarLayout 中的 title , 我们可以看到布局中的标题可以在折叠过程中移动至 toolBar 的位置(我觉得,在折叠完成后,系统自动会帮我们把 CollapsingToolbarLayout 中的 title 设为 toolBar 的 title , 如果我在设定 toolBar 的高度为 wrap_content 时,无论这样设定 CollapsingToolbarLayout 中的 title,都没有显示,应该是因为 toolBar 高度为 wrap_content,在没有位置显示 title ,所以 CollapsingToolbarLayout 中也不显示 title。这只是主观的猜测,有人知道就说说呗,告诉我这个新手)

我们可以通过多种属性设置 CollapsingToolbarLayout 中的 title 的在不同状态的内容和样式。一般来说,一个 xml 属性有对应的一个设置该属性的方法,我们可以在 xml 中设置属性,也可在代码中调用相应的方法。其实,一般一个类对象其中的字段就是对应的 xml 属性,我们在使用过程中,可以去查找其属性的用法就好了,因为这些属性太多了,实在是无法记忆的。如下:我们可以官网看起相关的类属性和类方法。
这里写图片描述

小结:系统提供的一些布局和控件用多了,发现不外乎是要掌握其属性的设置,不同的属性有不同的效果与功能,可以通过 xml 设置,也可以通过函数方法设置,在使用一个新布局或新控件时,我们可以通过看其文档介绍来查找一些需要的属性使用方法,同时我们也要脱离现象,想想完成一个动作效果,需要怎样的算法流程,例如在使用 TabLayout 时,我们可以想到这样一个情景,在导航栏切换 tab , 应该做出怎样的响应,在与之关联的布局切换内容区,应该做出怎样的响应,很容易想到的是,需要互相监听,我们想到的做法就是去看看布局对应的类中有没有什么 Listener 中可用等。好啦,我的意思是无论这样,一个动作效果对应的算法流程是基本不变的,无论你用什么编程语言去实现这个效果。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值