Android基础知识——Material Design实战

1.什么是Material Design

Material Design是由谷歌的设计工程师们基于传统的优秀设计原则,结合丰富的创意和科学技术所发明的一套全新的界面设计语言,包含了视觉,运动,互动效果等特性。而事实上,Material Design更像是一种设计思想和理念,而本节我们并不是要以设计师的角度去学习Material Design,而是以一个开发者的角度去学习使用一些符合Material Design理念的一些控件。

2.Toolbar

Toolbar继承了ActionBar的所有功能,而且灵活性很高,可以配合其他控件来完成一些Material Design的效果。

基本使用步骤:
1.更改程序的标题栏主题。
2.在布局中加入Toolbar。
3.在活动中替换标题栏。

示例:

//步骤一,values下的styles文件
<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">//因为我们要引入toolbar,所以这里选择无标题栏主题
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
</resources>
//步骤二
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"//单独令标题栏为深色主题
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />//令标题栏中的菜单项为浅色主题

</LinearLayout>
//步骤三
public class MainActivity extends AppCompatActivity {
    
    

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);//将标题栏替换为toolbar
    }
}

更改toolbar上显示的文字:

我们可以在活动中加入android:label属性来指定toolbar上显示的文字。

给toolbar添加菜单项:

使用步骤与给普通的actionbar添加菜单项类似。

示例:

//菜单布局
<?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">
    <item
        android:id="@+id/back"
        android:icon="@drawable/back"
        android:title="Back"
        app:showAsAction="always" />//始终以图片的形式存在于标题栏

    <item
        android:id="@+id/setting"
        android:icon="@drawable/setting"
        android:title="Setting"
        app:showAsAction="ifRoom" />//如果空间允许则以图片的形式存在于标题栏,否则以文字的形式

    <item
        android:id="@+id/delete"
        android:icon="@drawable/delete"
        android:title="Delete"
        app:showAsAction="never" />//始终以文字的形式存在于标题栏
</menu>
//活动
public class MainActivity extends AppCompatActivity {
    
    

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    
    //引入菜单布局
        getMenuInflater().inflate(R.menu.toolbra,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    
    //给菜单中的各个菜单项设置点击事件
        switch (item.getItemId()){
    
    
            case R.id.back:
                finish();
                break;
            case R.id.setting:
                Toast.makeText(MainActivity.this,"setting",Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(MainActivity.this,"delete",Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
        return true;
    }
}

3.滑动菜单

就是我们手机上常见的侧拉栏。

3.1DrawerLayout

使用方法:

DrawerLayout布局只允许其下有两个直接子布局,第一个是主界面的布局,第二个是侧拉栏的布局。

示例:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />


    </FrameLayout>

    <TextView
        android:id="@+id/text_view"
        android:text="This is menu"
        android:background="#fff"
        android:textSize="30sp"
        android:layout_gravity="start"//侧拉栏的布局必须声明这一属性,left表示侧拉栏在左,right表示侧拉栏在右,start则会根据系统语言来自动选择
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.drawerlayout.widget.DrawerLayout>

一个小问题:

这里可能存在一个问题,用户可能并不知道你的程序会有侧拉栏的功能,所以这里谷歌建议我们在标题栏中添加一个侧拉栏对应的按钮,用于打开侧拉栏。

示例:

public class MainActivity extends AppCompatActivity {
    
    

    private DrawerLayout drawerLayout;

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar);
        drawerLayout=(DrawerLayout) findViewById(R.id.drawer_layout);
        setSupportActionBar(toolbar);
        ActionBar actionBar=getSupportActionBar();
        if(actionBar!=null){
    
    
            actionBar.setDisplayHomeAsUpEnabled(true);//toolbar的最左侧有一个系统默认存在的按钮,而该方法能让该按钮显示出来
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);//这个按钮本身的图案是一个返回的箭头,而这里我们可以更改它的图案
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    
    
        getMenuInflater().inflate(R.menu.toolbra,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    
    
        switch (item.getItemId()){
    
    
            case android.R.id.home://给这个系统默认存在的按钮添加点击事件
                drawerLayout.openDrawer(GravityCompat.START);
                break;
            case R.id.back:
                finish();
                break;
            case R.id.setting:
                Toast.makeText(MainActivity.this,"setting",Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(MainActivity.this,"delete",Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
        return true;
    }
}

3.2NavigationView

在上节中我们侧拉栏中的内容有些单薄,而NavigationView可以帮助我们很轻松的丰富侧拉栏中的内容。

使用步骤:

1.声名依赖。
2.准备好NavigationView的menu项。
3.准备好NavigationView的headerLayout
4.在布局中加入NavigationView。
5.可以在活动中给NavigationView的各个菜单项设置点击事件。

示例:

//步骤一
dependencies {
    
    
    implementation 'com.google.android.material:material:1.2.1'//material design的相关库
    implementation 'de.hdodenhof:circleimageview:3.1.0'//这是一个开源项目,可以帮助我们很轻松的实现图片圆形化的功能。
}
//步骤二
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">//表示组内的所有菜单项只能单选
        <item
            android:id="@+id/call"
            android:title="Call"
            android:icon="@drawable/nav_call" />

        <item
            android:id="@+id/friends"
            android:title="Friends"
            android:icon="@drawable/nav_friends" />

        <item
            android:id="@+id/location"
            android:title="Location"
            android:icon="@drawable/nav_location" />

        <item
            android:id="@+id/mail"
            android:title="Mail"
            android:icon="@drawable/nav_mail" />

        <item
            android:id="@+id/task"
            android:title="Task"
            android:icon="@drawable/nav_task" />
    </group>
</menu>
//步骤三
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:padding="10dp"
    android:background="@color/colorPrimary"
    android:layout_width="match_parent"
    android:layout_height="180dp">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/image_view"
        android:src="@drawable/nav_icon"
        android:layout_centerInParent="true"
        android:layout_width="70dp"
        android:layout_height="70dp" />

    <TextView
        android:id="@+id/mail"
        android:textColor="#fff"
        android:text="mail: [email protected]"
        android:layout_alignParentBottom="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/username"
        android:textColor="#fff"
        android:text="username: yangxu"
        android:layout_above="@+id/mail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>
//步骤四
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    </FrameLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_gravity="start"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:menu="@menu/nav_menu"
        app:headerLayout="@layout/header_layout"/>

</androidx.drawerlayout.widget.DrawerLayout>
//步骤五
final DrawerLayout drawerLayout=(DrawerLayout) findViewById(R.id.drawer_layout);
NavigationView navigationView=(NavigationView) findViewById(R.id.nav_view);
navigationView.setCheckedItem(R.id.call);//将call菜单项设置为选中状态
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    
    
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    
    //可以在这里使用switch语句区分各个菜单项
        drawerLayout.closeDrawers();
        return true;
    }
});

4.悬浮按钮和可交互提示

4.1FloatingActionButton

该控件可以帮助我们很轻松的实现悬浮按钮的效果。

示例:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:src="@drawable/ic_done"
        android:layout_margin="16dp"
        android:layout_gravity="bottom|end"//此处的end同样也是根据系统语言来自动选择left或right
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:elevation="8dp"/>//该属性可以调整悬浮按钮下的阴影状态
        
</FrameLayout>

//我们还可以给这个悬浮按钮注册一个点击事件
FloatingActionButton fab=(FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
    
    
    @Override
    public void onClick(View view) {
    
    
        Toast.makeText(MainActivity.this,"ok",Toast.LENGTH_SHORT).show();
    }
});

4.2Snackbar

在此之前我们向用户发送提示信息时最常用的便是Toast了,但是Toast仅仅只能通知用户一些简单的信息,而用户则只能被动接收,因为没有什么办法能让用户来进行选择。

现在让我们设想一个场景当用户在删除文件时,如果不小心删除了几个重要的文件,假设我们只是用Toas来提示用户而没有给出取消的方法时,相信用户肯定会抓狂吧。而Snackbar则可以很好的解决这个问题。

示例:

fab.setOnClickListener(new View.OnClickListener() {
    
    
    @Override
    public void onClick(View view) {
    
    
        Snackbar.make(view,"you delete some import data",Snackbar.LENGTH_SHORT).setAction("Undo", new View.OnClickListener() {
    
    //setAction()方法的第一个参数是按钮名,第二个是监听器
            @Override
            public void onClick(View view) {
    
    a
                Toast.makeText(MainActivity.this,"Data restored",Toast.LENGTH_SHORT).show();
            }
        }).show();
    }
});

4.3CoordinatorLayout

如果你已经运行了我们在上面讲的代码的话,那你一定会发现Snackbar的提示信息将我们的悬浮按钮给遮挡住了,这样是十分影响界面的美观的,而我们本节要讲的CoordinatorLayout就可以解决这个问题了。

CoordinatorLayout是一个升级版的FrameLayout,它可以监听其所有子控件的各种事件,然后帮助我们做出最为合理的响应。

示例:

<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:src="@drawable/ic_done"
        android:layout_margin="16dp"
        android:layout_gravity="bottom|end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:elevation="8dp"/>
        
</androidx.coordinatorlayout.widget.CoordinatorLayout>

5.卡片式布局

5.1CardView

卡片式布局中的所有控件都将被放置在一张卡片上,给人一种立体的感觉,接下来我们就用RecyclerView来展示卡片布局的特点。

示例:

//主活动布局
<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
//RecyclerView子项布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_margin="5dp"
    app:cardCornerRadius="4dp"//该属性用来指定卡片布局圆角的弧度
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/fruit_image"
            android:src="@drawable/orange"
            android:scaleType="centerCrop"//该属性表示以同步的比例对图片进行缩放
            android:layout_width="match_parent"
            android:layout_height="100dp" />

        <TextView
            android:id="@+id/fruit_name"
            android:text="orange"
            android:textSize="16sp"
            android:layout_margin="5dp"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</androidx.cardview.widget.CardView>
//子项的类
public class Fruit {
    
    
    private String name;
    private int image;
    
    public Fruit(String name,int image){
    
    
        this.image=image;
        this.name=name;
    }

    public String getName() {
    
    
        return name;
    }

    public int getImage() {
    
    
        return image;
    }
}
//RecyclerView的适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    
    

    private List<Fruit> mList;

    public MyAdapter(List<Fruit> list){
    
    
        mList=list;
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
    
    
        TextView name;
        ImageView image;
        public ViewHolder(@NonNull View itemView) {
    
    
            super(itemView);
            name=itemView.findViewById(R.id.fruit_name);
            image=itemView.findViewById(R.id.fruit_image);
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout,parent,false);
        ViewHolder viewHolder=new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    
    
        Fruit fruit=mList.get(position);
        holder.name.setText(fruit.getName());
        holder.image.setImageResource(fruit.getImage());
    }

    @Override
    public int getItemCount() {
    
    
        return mList.size();
    }
}
//主活动
private List<Fruit> list=new ArrayList<>();

initFruits();
RecyclerView recyclerView=(RecyclerView) findViewById(R.id.recycler_view);
GridLayoutManager manager=new GridLayoutManager(this,2);
recyclerView.setLayoutManager(manager);
MyAdapter adapter=new MyAdapter(list);
recyclerView.setAdapter(adapter);

public void initFruits(){
    
    
    for(int i=0;i<50;i++){
    
    
        Fruit fruit=new Fruit("orange",R.drawable.orange);
        list.add(fruit);
    }
}

5.2AppBarLayout

如果你已经运行过上一节示例中的代码的话,那么你一定会发现RecyclerView布局将Toolbar标题栏给遮挡住了,这同样会影响我们界面的美观,而我们在本节中要学的AppBarLayout就可以解决这个问题了。

AppBarLayout实际上是一个垂直方向上的LinearLayout,不同的是它在内部做了很多滚动事件的封装,并应用了Material Design的设计理念。

示例:

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:layout_scrollFlags="scroll|snap|enterAlways"/>
        //该属性可以使控件更好的配合滑动事件。
        //其中scroll表示当recyclerview向上滚动时,Toolbar会跟着一起向上移动并实现隐藏;
		//snap表示当Toolbar还没有完全隐藏或显示时,会根据当前的距离自动选择隐藏还是显示;
		//enterAlways表示当recyclerview向下滚动时,Toolbar会跟着向下移动并重新显示。
        
</com.google.android.material.appbar.AppBarLayout>

<androidx.recyclerview.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"/>//我们这里让recyclerview向下偏移一个标题栏的长度

6.下拉刷新

我们在日常使用app时,经常会用到下拉刷新这个功能,而在本节中我们就来实现该功能。

示例:

<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
    android:id="@+id/swipe_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
        
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

//我们还要在活动中去处理刷新的逻辑
final SwipeRefreshLayout swipeRefreshLayout=(SwipeRefreshLayout) findViewById(R.id.swipe_layout);
swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);//设置进度条的颜色
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    
    
    @Override
    public void onRefresh() {
    
    
        //刷新的逻辑代码,此处一般是从网咯中获取数据,因此会开辟一个线程来进行处理。
        swipeRefreshLayout.setRefreshing(false);//刷新完成后,关闭进度条
    }
});

7.可折叠式标题栏

7.1CollapsingToolbarLayout

我们可以利用CollapsingToolbarLayout布局,来帮助我们实现可折叠式的标题栏。不过CollapsingToolbarLayout是不能单独存在的,它只能作为AppBarLayout的直接子布局来使用,而AppBarLayout又必须是CoordinatorLayout的子布局。接下来我们就来看一个CollapsingToolbarLayout的示例吧。

示例:

//新活动的布局
<androidx.coordinatorlayout.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">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="250dp">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:contentScrim="?attr/colorPrimary"//该属性用于设置当标题栏完全折叠式的背景颜色
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/fruit_image_view"
                android:src="@drawable/orange"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"/>//该属性表示该控件会随着折叠而折叠

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar02"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"/>//该属性表示该控件不会随着折叠而折叠


        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="35dp"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginBottom="15dp"
                app:cardCornerRadius="4dp">

                <TextView
                    android:id="@+id/fruit_content_text"
                    android:layout_margin="10dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>

            </androidx.cardview.widget.CardView>

        </LinearLayout>

    </androidx.core.widget.NestedScrollView>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_comment"
        app:layout_anchor="@id/appBar"//该属性用于给悬浮按钮定义一个锚点
        app:layout_anchorGravity="bottom|end" />//该属性用于设置悬浮按钮相对于锚点的位置

</androidx.coordinatorlayout.widget.CoordinatorLayout>
//新活动的代码
public class MainActivity2 extends AppCompatActivity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Intent intent=getIntent();
        String name=intent.getStringExtra("name");
        int image=intent.getIntExtra("image",-1);
        Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar02);
        CollapsingToolbarLayout collapsingToolbarLayout=(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        ImageView fruitImage=(ImageView) findViewById(R.id.fruit_image_view);
        TextView fruitContent=(TextView) findViewById(R.id.fruit_content_text);
        setSupportActionBar(toolbar);
        ActionBar actionBar=getSupportActionBar();
        if(actionBar!=null){
    
    
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
        collapsingToolbarLayout.setTitle(name);
        fruitImage.setImageResource(image);
        StringBuilder content=new StringBuilder();
        for(int i=0;i<3000;i++){
    
    
            content.append(name);
        }
        fruitContent.setText(content.toString());
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    
    
        switch (item.getItemId()){
    
    
            case android.R.id.home:
                finish();
                break;
            default:
        }
        return super.onOptionsItemSelected(item);
    }
}
//recyclerview的适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    
    

    private List<Fruit> mList;

    public MyAdapter(List<Fruit> list){
    
    
        mList=list;
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
    
    
        View view;
        TextView name;
        ImageView image;
        public ViewHolder(@NonNull View itemView) {
    
    
            super(itemView);
            view=itemView;
            name=itemView.findViewById(R.id.fruit_name);
            image=itemView.findViewById(R.id.fruit_image);
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, int viewType) {
    
    
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout,parent,false);
        final ViewHolder viewHolder=new ViewHolder(view);
        viewHolder.view.setOnClickListener(new View.OnClickListener() {
    
    //设置点击事件
            @Override
            public void onClick(View view) {
    
    
                int position=viewHolder.getAdapterPosition();
                Fruit fruit=mList.get(position);
                Intent intent=new Intent(parent.getContext(),MainActivity2.class);
                intent.putExtra("name",fruit.getName());
                intent.putExtra("image",fruit.getImage());
                parent.getContext().startActivity(intent);//开启新活动
            }
        });
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    
    
        Fruit fruit=mList.get(position);
        holder.name.setText(fruit.getName());
        holder.image.setImageResource(fruit.getImage());
    }

    @Override
    public int getItemCount() {
    
    
        return mList.size();
    }
}

7.2充分利用系统状态栏空间

如果你运行了我们上一节中的代码,那么你一定发现了系统状态栏哪里感觉与我们的界面非常不搭配,而要解决这一问题也非常简单,只需把系统状态栏设置为透明色即可。

示例:

//首先给你要实现融合的控件及其父布局都设置上android:fitsSystemWindows="true"属性
<androidx.coordinatorlayout.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:fitsSystemWindows="true">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:fitsSystemWindows="true"
        android:layout_height="250dp">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:contentScrim="?attr/colorPrimary"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/fruit_image_view"
                android:src="@drawable/orange"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                android:fitsSystemWindows="true"/>

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar02"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"/>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="35dp"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginBottom="15dp"
                app:cardCornerRadius="4dp">

                <TextView
                    android:id="@+id/fruit_content_text"
                    android:layout_margin="10dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>

            </androidx.cardview.widget.CardView>

        </LinearLayout>

    </androidx.core.widget.NestedScrollView>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_comment"
        app:layout_anchor="@id/appBar"
        app:layout_anchorGravity="bottom|end" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

//将系统状态栏的颜色设置为透明色(因为只有在Android5.0后我们才可以这样做,因此我们要对此做区分)
//values-v21下的styles文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="FruitActivityTheme" parent="AppTheme">//使其继承自AppTheme,这样AppTheme所拥有的特性它也会拥有
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>
//values下的styles文件
<resources>
    <!-- Base application theme. -->
    <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>

    <style name="FruitActivityTheme" parent="AppTheme">
    </style>

</resources>

//给第二个活动使用我们新建的主题
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.temp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity2"
            android:theme="@style/FruitActivityTheme" />
        <activity
            android:name=".MainActivity"
            android:label="MyBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

猜你喜欢

转载自blog.csdn.net/ABded/article/details/108554840