Material Design

最佳的UI体验-----Material Design实战

使用Material Design来设计界面

Toolbar

Toolbar的强大之处在于,它不仅继承了ActionBar的所有功能,而且灵活性很高,可以配合其他控件来完成一些Material Design的效果.

新建一个项目都会显示ActionBar其实是跟项目中指定的主题来显示的,打开AndroidMainfest.xml,如下:

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:theme="@style/AppTheme"
        ...
 </application>

AppTheme在哪定义的呢?

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Base.Theme.Mytest" parent="Theme.Material3.DayNight.NoActionBar">
        <!-- Customize your dark theme here. -->
        <!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
    </style>
</resources>

现在使用Toolar来替代ActionBar.修改布局:

<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">
    <com.google.android.material.appbar.MaterialToolbar
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:id="@+id/toolbar"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</FrameLayout>

然后接着修改MainActivity

public class MainActivity extends AppCompatActivity {

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

其中,这边会有一个错误:

img

这个错误主要来源于,其导包错误,导成了

import android.widget.Toolbar;

而在选择时,应该选为

import androidx.appcompat.widget.Toolbar;

修改后的代码:

img

为了使Toolbar更加丰富一点,准备几张图片来作为按钮的图标,右击res目录→New→Directory,创建一个menu文件夹,然后右击menu文件夹→New→Menu resource file,创建一个toolbar.xml文件,编写代码:

<?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/backup"
        android:icon="@drawable/ic_launcher_background"
        android:title="Backup"
        app:showAsAction="always" />
    <item
        android:id="@+id/delete"
        android:icon="@drawable/ic_launcher_foreground"
        android:title="Delete"
        app:showAsAction="always" />
    <item
        android:id="@+id/settings"
        android:icon="@mipmap/ic_launcher"
        android:title="Settings"
        app:showAsAction="never" />

</menu>

通过标签来定义action按钮,android:id用于指定按钮的id,android:icon用于指定按钮的图标,android:title用于指定按钮的文字.

app:showAsAction来指定按钮的显示位置,之所以这里再次使用了app命名空间,同样是为了能够兼容低版本的系统.showAsAction主要有以下几种值可选:always表示永远显示在Toolbar中,如果屏幕空间不够则不显示;ifRoom表示屏幕空间足够的情况下显示在Toolbar中,不够的话就显示在菜单中;never则表示永远显示在菜单当中.注意:Toolbar中的action按钮只会显示图标,菜单中的action按钮只会显示文字.

接着,修改MainActivity中的代码,如下:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.toolbar,menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        if(item.getItemId() == R.id.backup){
            Toast.makeText(this, "You clicked Backup", Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.delete){
            Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.settings){
            Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
        }
        return true;
    }
}

逻辑十分简单,在onCreateOptionsMenu()方法中加载了toolbar.xml菜单文件,然后在onOptionsItemSelected()方法中处理各个按钮的点击事件

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

滑动菜单

DrawerLayout

所谓的滑动菜单就是将一些菜单选项隐藏起来,而不是放置在主屏幕上,然后通过滑动的方式将菜单显示出来.这种方式既节省了屏幕空间,有实现了非常好的动画效果,是比较推荐的.

DrawerLayout首先他是一个布局,在布局中允许放入两个直接子控件,第一个子控件是主屏幕中显示的内容,第二个子控件是滑动菜单中显示的内容,对布局进行修改:

<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:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.google.android.material.appbar.MaterialToolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </FrameLayout>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:text="This is menu"
        android:textSize="30sp"
        android:background="#FFF" />
</androidx.drawerlayout.widget.DrawerLayout>

可以看到,最外层的控件使用了DrawerLayout,DrawerLayout中放置了两个直接子控件,第一个子控件是FrameLayout,用于作为主屏幕中显示的内容,当然里面还有刚定义的Toolbar.第二个子控件使用了一个TextView,用于作为滑动菜单中显示的内容.

关于第二个子控件需要注意:layout_gravity这个属性是必须指定的,因为需要告诉DrawerLayout滑动菜单是在屏幕的左边还是右边,指定left表示滑动菜单在左边,指定right表示滑动菜单在右边,指定start,表示会根据系统语言进行判断.

现在可以在Toolbar的最左边加入一个导航按钮,点击了按钮也会将滑动菜单的内容展示出来.首先准备了一张导航图片,ic_menu.png,将它放在mimap-xxxhdpi目录下,然后修改MainActivity中的代码,如下:

public class MainActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeAsUpIndicator(R.mipmap.ic_menu);
        }
    }
    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.toolbar,menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        if(item.getItemId() == R.id.backup){
            Toast.makeText(this, "You clicked Backup", Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.delete){
            Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.settings){
            Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == android.R.id.home){
            mDrawerLayout.openDrawer(GravityCompat.START);
        }
        return true;
    }
}

首先调用findViewById()方法得到了DrawerLayout的实例,然后调用getSupportActionBar()方法得到了ActionBar的实例,接着调用ActionBar的setDisplayHomeAsUpEnabled()方法让导航按钮显示出来,又调用setHomeAsUpIdicator()方法设置了一个导航按钮图标,实际上,Toolbar最左侧的这个按钮就是叫做HomeAsUp按钮,他默认的是一个返回的箭头,含义是返回上一个活动

接下来在onOptionsItemSelected()方法中对HomeAsUp按钮的点击事件进行处理,HomeAsUp按钮的id永远是android.R.id.home.然后调用DrawerLayout的openDrawer()方法将滑动菜单展示出来

NavigationView

第一步:添加如下依赖:

implementation 'de.hdodenhof:circleimageview:3.1.0'

这个依赖的作用就是可以用来轻松实现图片圆形化的功能.

在使用NavigationView之前,还需要准备两个东西:menu和headerLayout.menu是用来在NavigationView中显示具体的菜单项,headerLayout则是用来在NavigationView中显示头部布局的.

先来准备menu,实现找了几张图片作为按钮的图标,并将他们放在了mimap-xxxhdpi目录下,然右击menu文件夹→New→Menu resource file,创建一个nav_menu.xml文件,然后编写以下代码:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_call"
            android:icon="@mipmap/collect_select"
            android:title="Call" />
        <item
            android:id="@+id/nav_friends"
            android:icon="@mipmap/collect_selected"
            android:title="Friends"/>
        <item
            android:id="@+id/nav_location"
            android:icon="@mipmap/ic_launcher"
            android:title="Location" />
        <item
            android:id="@+id/nav_mail"
            android:icon="@mipmap/pwd"
            android:title="Mail" />
        <item
            android:id="@+id/nav_task"
            android:icon="@mipmap/my_selected"
            android:title="Tasks" />
    </group>
</menu>="single">
        <item
            android:id="@+id/nav_call"
            android:icon="@mipmap/collect_select"
            android:title="Call" />
        <item
            android:id="@+id/nav_friends"
            android:icon="@mipmap/collect_selected"
            android:title="Friends"/>
        <item
            android:id="@+id/nav_location"
            android:icon="@mipmap/ic_launcher"
            android:title="Location" />
        <item
            android:id="@+id/nav_mail"
            android:icon="@mipmap/pwd"
            android:title="Mail" />
        <item
            android:id="@+id/nav_task"
            android:icon="@mipmap/my_selected"
            android:title="Tasks" />
    </group>
</menu>

其中,group表示一个组,checkableBehavior指定为single表示组中的所有菜单项只能单选.

接下来准备headerLayout,这是一个可以随意定制的布局,可以在headerLayout中放置头像,用户名,邮箱地址

最好准备一张正方形图片,右击layout文件夹→New→Layout resource file,创建一个nav_header.xml文件,代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:padding="10dp"
    android:background="?attr/colorPrimary">
    <de.hdodenhof.circleimageview.CircleImageView
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:id="@+id/icon_image"
        android:src="@mipmap/img"
        android:layout_centerInParent="true" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id = "@+id/mail"
        android:layout_alignParentBottom="true"
        android:text="tonygreendev@gmail.com"
        android:textColor="#FFF"
        android:textSize="14sp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/username"
        android:layout_above="@+id/mail"
        android:text="Tony Green "
        android:textColor="#FFF"
        android:textSize="14sp" />
</RelativeLayout>

现在menu和headerLayout都准备好了,可以使用NavigationView.修改activity_main.xml中的代码:

<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:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.google.android.material.appbar.MaterialToolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </FrameLayout>
   <com.google.android.material.navigation.NavigationView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/nav_view"
       android:layout_gravity="start"
       app:menu="@menu/nav_menu"
       app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>

将之前的TextView换成了NavigationView,这样滑动菜单中显示的内容也就变成了NavigationView了 app:menu和 app:headerLayout将刚才设置好的东西设置进去了.

public class MainActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeAsUpIndicator(R.mipmap.ic_menu);
        }
        navView.setCheckedItem(R.id.nav_call);
        navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                mDrawerLayout.closeDrawers();
                return true;
            }
        });
    }
    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.toolbar,menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        if(item.getItemId() == R.id.backup){
            Toast.makeText(this, "You clicked Backup", Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.delete){
            Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.settings){
            Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == android.R.id.home){
            mDrawerLayout.openDrawer(GravityCompat.START);
        }
        return true;
    }
}

悬浮按钮和可交互提示

FloatingActionButton

此控件可以帮助我们轻松的实现悬浮按钮的效果,准备一张图片,然后修改activity_main.xml中的代码,如下:

<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:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.google.android.material.appbar.MaterialToolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fab"
            android:layout_gravity="bottom|end"  //将这个控件放入到了屏幕的右下角
            android:layout_margin="16dp"
            android:src="@mipmap/dianzan"
            app:elevation="8dp"/>
    </FrameLayout>
   <com.google.android.material.navigation.NavigationView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/nav_view"
       android:layout_gravity="start"
       app:menu="@menu/nav_menu"
       app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>

然后在MainActivity中增加点击事件:

public class MainActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"FAB clicked",Toast.LENGTH_SHORT).show();
            }
        });
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeAsUpIndicator(R.mipmap.ic_menu);
        }
        navView.setCheckedItem(R.id.nav_call);
        navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                mDrawerLayout.closeDrawers();
                return true;
            }
        });
    }
    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.toolbar,menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        if(item.getItemId() == R.id.backup){
            Toast.makeText(this, "You clicked Backup", Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.delete){
            Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.settings){
            Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == android.R.id.home){
            mDrawerLayout.openDrawer(GravityCompat.START);
        }
        return true;
    }
}
Snackbar

之前处理点击事件时,都是使用Toast来作为提示工具的,Snackbar就是更为先进的提示工具.

Toast只能进行提示,而Snackbar可以进行交互

修改MainActivity中的代码

fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view,"Data deleted",Snackbar.LENGTH_SHORT)
                        .setAction("Undo", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(MainActivity.this,"Data restored",
                                        Toast.LENGTH_SHORT).show();
                            }
                        }).show();
            }
        });

这里调用了Snackbar的make()方法来创建一个Snackbar对象,make()方法中的第一个参数传入一个View,只要是当前布局的任意一个View即可,Snackbar会使用这个View来自动查找最外层的布局,用于显示Snackbar.第二个参数是Snackbar中显示的内容,第三个参数是Snackbar显示的时长

但是有一个问题,Snackbar会将悬浮按钮给挡住,这样子用户体验不是很好.需要借助CoordinatorLayout解决.

CoordinatorLayout

CoordinatorLayout是一个加强版的FrameLayout,其可以监听所有子控件的各种事件,然后帮我们做出最为合理的响应.例如:刚才弹出的Snackbar提示将悬浮按钮挡住了,如果我们能让CoordinatorLayout监听到Snackbar的弹出事件,他就会自动的将内部的FloatingActionButton向上偏移

修改布局中的代码,

<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:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.google.android.material.appbar.MaterialToolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/dianzan"
            app:elevation="8dp"/>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
   <com.google.android.material.navigation.NavigationView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/nav_view"
       android:layout_gravity="start"
       app:menu="@menu/nav_menu"
       app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>

CoordinatorLayout可以监听其所有子控件的各种事件,但是Snackbar好像并不是CoordinatorLayout的子控件

因为在Snackbar的make()方法,第一个参数VIew是FloatingAActionBar触发的,而FloatingActionBar是Coordu=inatorLayout中的子控件.

卡片式布局

CardView

由于在此程序中,实现我们需要RecyclerView,CardView这几个控件,因此我们要加入如下依赖:

implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.9.0'

最后一行是Glide库的依赖,Glide是一个超级强大的图片加载器.

接下来修改activity_main.xml中的代码,如下:

<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:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.google.android.material.appbar.MaterialToolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/recycler_view" />
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/dianzan"
            app:elevation="8dp"/>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
   <com.google.android.material.navigation.NavigationView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/nav_view"
       android:layout_gravity="start"
       app:menu="@menu/nav_menu"
       app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>

然后定义一个Fruit类,如下:

public class Fruit {
    private String name;
    private int imageId;
    public Fruit(String name,int imageId){
        this.name = name;
        this.imageId = imageId;
    }

    public String getName() {
        return name;
    }
    public int getImageId() {
        return imageId;
    }
}

然后需要为RecyclerView的子项指定一个我们自定义的布局,在layout目录下新建fruit_item.xml,代码如下:

<androidx.cardview.widget.CardView
    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="wrap_content"
    android:layout_margin="5dp"
    app:cardCornerRadius="4dp" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:scaleType="centerCrop"
            android:id="@+id/fruit_image"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fruit_name"
            android:layout_gravity="center_horizontal"
            android:layout_margin="5dp"
            android:textSize="16sp" />
    </LinearLayout>
</androidx.cardview.widget.CardView>

这里使用CardView来作为子项的最外层布局,从而使得RecyclerView中的每个元素都是在卡片中的.

这里注意在ImageView中我们使用了一个scaleType属性,这个属性可以指定图片的缩放模式.由于各张水果图片的长宽比例可能都不一样,为了让所有的图片填充整个ImageView,这里使用了centerCrop模式

然后新建一个FruitAdapter类

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    private Context mContext;
    private List<Fruit> mFruitList;
    static class ViewHolder extends RecyclerView.ViewHolder{
        CardView cardView;
        ImageView fruitImage;
        TextView fruitName;
        public ViewHolder(View view){
            super(view);
            cardView = (CardView) view;
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);
        }
    }
    public FruitAdapter(List<Fruit> fruitList){
        mFruitList = fruitList;
    }
    @NonNull
    @Override
    public FruitAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if(mContext == null){
            mContext = parent.getContext();
        }
        View view = LayoutInflater.from(mContext).inflate(R.layout.fruit_item,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull FruitAdapter.ViewHolder holder, int position) {
         Fruit fruit = mFruitList.get(position);
         holder.fruitName.setText(fruit.getName());
        Glide.with(mContext).load(fruit.getImageId()).into(holder.fruitImage);
    }

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

其中Glide在内部做了很多非常复杂的逻辑,其中就包括了图片的压缩等,比较方便.

最后修改MainActivity中的代码,如下:

public class MainActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    private Fruit[] fruits = {new Fruit("Apple",R.mipmap.apple),
            new Fruit("Orange",R.mipmap.orange),
            new Fruit("Watermelon",R.mipmap.watermelon),
            new Fruit("Pear",R.mipmap.pear),
            new Fruit("Grape",R.mipmap.grape)};
    private List<Fruit> fruitList = new ArrayList<>();
    private FruitAdapter adapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
        initFruits();
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        GridLayoutManager layoutManager = new GridLayoutManager(this,2);
        recyclerView.setLayoutManager(layoutManager);
        adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view,"Data deleted",Snackbar.LENGTH_SHORT)
                        .setAction("Undo", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(MainActivity.this,"Data restored",
                                        Toast.LENGTH_SHORT).show();
                            }
                        }).show();
            }
        });
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeAsUpIndicator(R.mipmap.ic_menu);
        }
        navView.setCheckedItem(R.id.nav_call);
        navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                mDrawerLayout.closeDrawers();
                return true;
            }
        });
    }

    private void initFruits() {
        fruitList.clear();
        for(int i =0 ; i < 50; i++){
            Random random = new Random();
            int index = random.nextInt(fruits.length);
            fruitList.add(fruits[index]);
        }
    }

    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.toolbar,menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        if(item.getItemId() == R.id.backup){
            Toast.makeText(this, "You clicked Backup", Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.delete){
            Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.settings){
            Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == android.R.id.home){
            mDrawerLayout.openDrawer(GravityCompat.START);
        }
        return true;
    }
}
AppBarLayout

因为此时出现了RecyclerView会把Toolbar遮挡住,此时的解决办法就是让RecyclerView向下偏移了一个Toolbar的高度,从而保证不会遮挡到Toolbar

使用AppBarLayout怎样解决问题?第一步将Toolbar嵌套到AppBarLayout中,第二步给RecyclerView指定一个布局行为.

修改activity_main.xml中的代码,如下:

<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:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        <com.google.android.material.appbar.MaterialToolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways|snap"/>
    </com.google.android.material.appbar.AppBarLayout>
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/recycler_view"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/dianzan"
            app:elevation="8dp"/>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
   <com.google.android.material.navigation.NavigationView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/nav_view"
       android:layout_gravity="start"
       app:menu="@menu/nav_menu"
       app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>

在进行一下优化,修改activity_main.xml中的代码,如下:

<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:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        <com.google.android.material.appbar.MaterialToolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways|snap"/>
    </com.google.android.material.appbar.AppBarLayout>
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/recycler_view"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/dianzan"
            app:elevation="8dp"/>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
   <com.google.android.material.navigation.NavigationView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/nav_view"
       android:layout_gravity="start"
       app:menu="@menu/nav_menu"
       app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>

在Toolbar中添加了一个app:layout_scrollFlags属性,并将属性的值指定成了scroll|enterAlways|snap.其中,scroll表示当RecyclerView向上滚动的时候,Toolbar会跟着一起向上滚动并实现隐藏;enterAlways表示当RecyclerView向下滚动的时候,Toolbar会跟着一起向下滚动并重新显示;snap表示当Toolbar还没有完全隐藏或显示的时候,会根据当前滚动的距离,自动选择隐藏还是显示.

下拉刷新

首先需要添加依赖:

 implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"

我们把想要实现下拉刷新功能的控件放置到SwipeRefreshLayout中,就可以让这个控件支持下拉刷新,而此时的控件应该是RecyclerView

修改activity_main.xml中的代码,如下:

<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:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        <com.google.android.material.appbar.MaterialToolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways|snap"/>
    </com.google.android.material.appbar.AppBarLayout>
        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/swipe_refresh"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">
            <androidx.recyclerview.widget.RecyclerView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/recycler_view" />

        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/dianzan"
            app:elevation="8dp"/>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
   <com.google.android.material.navigation.NavigationView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/nav_view"
       android:layout_gravity="start"
       app:menu="@menu/nav_menu"
       app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>

修改MainActivity中的代码:

public class MainActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    private SwipeRefreshLayout swipeRefresh;
    private Fruit[] fruits = {new Fruit("Apple",R.mipmap.apple),
            new Fruit("Orange",R.mipmap.orange),
            new Fruit("Watermelon",R.mipmap.watermelon),
            new Fruit("Pear",R.mipmap.pear),
            new Fruit("Grape",R.mipmap.grape)};
    private List<Fruit> fruitList = new ArrayList<>();
    private FruitAdapter adapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
        initFruits();
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        GridLayoutManager layoutManager = new GridLayoutManager(this, 2);
        recyclerView.setLayoutManager(layoutManager);
        adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
        swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
        swipeRefresh.setColorSchemeResources(com.google.android.material.R.color.design_default_color_primary);
        swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshFruits();
            }
        });

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view,"Data deleted",Snackbar.LENGTH_SHORT)
                        .setAction("Undo", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(MainActivity.this,"Data restored",
                                        Toast.LENGTH_SHORT).show();
                            }
                        }).show();
            }
        });
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeAsUpIndicator(R.mipmap.ic_menu);
        }
        navView.setCheckedItem(R.id.nav_call);
        navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                mDrawerLayout.closeDrawers();
                return true;
            }
        });
    }

    private void refreshFruits() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    Thread.sleep(2000);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        initFruits();
                        adapter.notifyDataSetChanged();
                        swipeRefresh.setRefreshing(false);
                    }
                });
            }
        }).start();
    }

    private void initFruits() {
        fruitList.clear();
        for(int i =0 ; i < 50; i++){
            Random random = new Random();
            int index = random.nextInt(fruits.length);
            fruitList.add(fruits[index]);
        }
    }

    public boolean onCreateOptionsMenu(Menu menu){
        getMenuInflater().inflate(R.menu.toolbar,menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        if(item.getItemId() == R.id.backup){
            Toast.makeText(this, "You clicked Backup", Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.delete){
            Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == R.id.settings){
            Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
        }if(item.getItemId() == android.R.id.home){
            mDrawerLayout.openDrawer(GravityCompat.START);
        }
        return true;
    }
}

可折叠式标题栏

CollapsingToolbarLayout

CollapsingToolbarLayout是不能单独存在的,他只能作为AppBarLayout的直接子布局来使用,而AppBarLayout又必须是CoordinatorLayout的子布局

首先需要一个额外的活动来作为水果的详情展示页面,

在activity_fruit.xml中的内容主要分为两部分,一个是水果标题栏,一个是水果内容详情.

首先是实现标题栏部分,这里使用CoordinatorLayout来作为最外层布局,接着在CoordinatorLayout中嵌套一个AppBarLayout,接下来再在AppBarLayout中再嵌套一个CollapsingToolbarLayout.接下来在CollapsingToolbarLayout中定义标题栏的内容,在里面定义了一个ImageView和一个Toolbar.

这样就将水果标题栏的界面编写完成了,下面开始编写水果页面的内容详细部分.

水果内容详细的最外层布局就是使用了一个NestedScrollView,它和AppBarLLayout是平级的.

不管是ScrollView还是NestedSrollView,它们的内部都是只允许存在一个直接子布局,因此,如果我们想要在里面放入很多东西的话,通常先会嵌套一个LinearLatout,然后再在LinearLayout中放入具体的内容就可以了.

在LinearLayout中放入具体的内容,这里准备一个TextView来显示水果的内容详情,并将TextView放入到一个卡片式布局当中.再放入一个悬浮按钮,此时,布局页面就好了.

<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:layout_width="match_parent"
        android:layout_height="250dp"
        android:id="@+id/appBar"
        android:fitsSystemWindows="true">
        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/collapsing_toolbar"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:contentScrim="?attr/colorPrimary"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/fruit_image_view"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />
            <androidx.appcompat.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:id="@+id/toolbar"
                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:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dp"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginTop="35dp"
                app:cardCornerRadius="4dp" >
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/fruit_content_text"
                    android:layout_margin="10dp" />
            </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="@mipmap/dianzan"
        app:layout_anchor="@id/appBar"
        app:layout_anchorGravity="bottom|end" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

接下来修改FruitActivity中的代码,如下:

public class FruitActivity extends AppCompatActivity {
    public static final String FRUIT_NAME = "fruit_name";
    public static final String FRUIT_IMAGE_ID = "fruit_image_id";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fruit);
        Intent intent = getIntent();
        String fruitName = intent.getStringExtra(FRUIT_NAME);
        int fruitImaged  = intent.getIntExtra(FRUIT_IMAGE_ID,0);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        CollapsingToolbarLayout collapsingToolbarLayout =
                (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        ImageView fruitImageView = (ImageView) findViewById(R.id.fruit_image_view);
        TextView fruitContentText = (TextView) findViewById(R.id.fruit_content_text);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
        collapsingToolbarLayout.setTitle(fruitName);
        Glide.with(this).load(fruitImaged).into(fruitImageView);
        String fruitContent = generateFruitContent(fruitName);
        fruitContentText.setText(fruitContent);
    }
    private String generateFruitContent(String fruitName){
        StringBuilder fruitContent = new StringBuilder();
        for(int i= 0; i < 500;i++){
            fruitContent.append(fruitName);
        }
        return fruitContent.toString();
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if(item.getItemId() == android.R.id.home){
            finish();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

接着在修改FruitAdapter中的代码,如下:

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    private Context mContext;
    private List<Fruit> mFruitList;
    static class ViewHolder extends RecyclerView.ViewHolder{
        CardView cardView;
        ImageView fruitImage;
        TextView fruitName;
        public ViewHolder(View view){
            super(view);
            cardView = (CardView) view;
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);
        }
    }
    public FruitAdapter(List<Fruit> fruitList){
        mFruitList = fruitList;
    }
    @NonNull
    @Override
    public FruitAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if(mContext == null){
            mContext = parent.getContext();
        }
        View view = LayoutInflater.from(mContext).inflate(R.layout.fruit_item,parent,false);
        final ViewHolder holder = new ViewHolder(view);
        holder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Intent intent = new Intent(mContext,FruitActivity.class);
                intent.putExtra(FruitActivity.FRUIT_NAME,fruit.getName());
                intent.putExtra(FruitActivity.FRUIT_IMAGE_ID,fruit.getImageId());
                mContext.startActivity(intent);
            }
        });
        return  holder;
    }

    @Override
    public void onBindViewHolder(@NonNull FruitAdapter.ViewHolder holder, int position) {
         Fruit fruit = mFruitList.get(position);
         holder.fruitName.setText(fruit.getName());
        Glide.with(mContext).load(fruit.getImageId()).into(holder.fruitImage);
    }

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

rent, int viewType) {
if(mContext == null){
mContext = parent.getContext();
}
View view = LayoutInflater.from(mContext).inflate(R.layout.fruit_item,parent,false);
final ViewHolder holder = new ViewHolder(view);
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Intent intent = new Intent(mContext,FruitActivity.class);
intent.putExtra(FruitActivity.FRUIT_NAME,fruit.getName());
intent.putExtra(FruitActivity.FRUIT_IMAGE_ID,fruit.getImageId());
mContext.startActivity(intent);
}
});
return holder;
}

@Override
public void onBindViewHolder(@NonNull FruitAdapter.ViewHolder holder, int position) {
     Fruit fruit = mFruitList.get(position);
     holder.fruitName.setText(fruit.getName());
    Glide.with(mContext).load(fruit.getImageId()).into(holder.fruitImage);
}

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

}














































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值