Android基础之Material Design | NavigationView | FloatingActionButton | SnakerBar等 | 带源码

Material Design

简介

  • 一套全新的界面设计语言,包含了视觉、运动、互动效果等特性

ToolBar

  • 在res下新建一个menu文件夹,新建一个toobar.xml文件
<menu xmlns:android="http://schemas.android.com/apk/res/android"
		    xmlns:app="http://schemas.android.com/apk/res-auto">
		    <!--  showAsAction的三种含义
		            always表示永远显示在toolBar中
		            ifRoom表示若屏幕空间足够显示在toolBar中
		            never表示永远显示在菜单当中
		            且toolBar中只会显示图片
		            菜单中只会显示文字-->
		    <item
		        android:id="@+id/backup"
		        android:icon="@drawable/ic_backup"
		        android:title="@string/backup"
		        app:showAsAction="always"/>
		    <item
		        android:id="@+id/delete"
		        android:icon="@drawable/ic_delete"
		        android:title="@string/delete"
		        app:showAsAction="ifRoom"/>
		    <item
		        android:id="@+id/settings"
		        android:icon="@drawable/ic_settings"
		        android:title="@string/settings"
		        app:showAsAction="never"/>

</menu>
  • activity_main.xml
<androidx.appcompat.widget.Toolbar
	        android:id="@+id/toolbar"
	        android:layout_width="match_parent"
	        android:layout_height="wrap_content"
	        android:background="?attr/colorPrimary"
	        android:minHeight="?attr/actionBarSize"
	        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
	        app:popupTheme="@style/Theme.AppCompat.Light"
	        app:layout_constraintEnd_toEndOf="parent"
	        app:layout_constraintStart_toStartOf="parent"
	        app:layout_constraintTop_toTopOf="parent" />
  • MainActivity
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        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(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.backup:
                Toast.makeText(this,"You clicked backup",Toast.LENGTH_SHORT).show();
                //能响应点击事件
                startActivity(new Intent(this,MainActivity.class));
                break;
            case R.id.delete:
                Toast.makeText(this,"You clicked delete",Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"You clicked settings",Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }
}

滑动菜单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">
	<!--  该控件用于作为主屏幕中显示的内容,以及toolBar  -->
	<FrameLayout
        	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="?attr/colorPrimary"
		            android:theme="@style/ThemeOverlay.AppCompat.DayNight.ActionBar"
		            app:popupTheme="@style/ThemeOverlay.AppCompat.DayNight" />
	</FrameLayout>
	<!--  layout_gravity指定了菜单所处的方向,且必须指定
		  如果是left就在左边,right就在右边,start表示跟随系统语言方向,从左往右就在左边-->
	<TextView
		    android:layout_width="match_parent"
		    android:layout_height="match_parent"
		    android:layout_gravity="start"
		    android:text="@string/this_is_menu"
		    android:textSize="30sp"
		    android:background="#FFF" />
</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 = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //得到DrawerLayout实例
        mDrawerLayout = findViewById(R.id.drawer_layout);
        //得到ActionBar实例,具体实现由ToolBar来完成
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            //让导航按钮显示出来
            actionBar.setDisplayHomeAsUpEnabled(true);
            //设置一个导航按钮图标,将图片传进去
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        }
    }

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

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
                //HomeAsUp的图标的id永远是这一个
            case android.R.id.home:
                //调用该方法将菜单展示出来,传入的参数是Gravity参数
                mDrawerLayout.openDrawer(GravityCompat.START);
                break;
            case R.id.backup:
                Toast.makeText(this,"You clicked backup",Toast.LENGTH_SHORT).show();
                //能响应点击事件
                startActivity(new Intent(this,MainActivity.class));
                break;
            case R.id.delete:
                Toast.makeText(this,"You clicked delete",Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"You clicked settings",Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }
}

滑动菜单控件NavigationView

  • 在menu中新建一个nav_menu.xml文件
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!--  在menu里面嵌套一个group,将之属性设置为single,表示菜单中的所有属性只能单选  -->
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_call"
            android:icon="@drawable/nav_call"
            android:title="@string/nav_call"/>
        <item
            android:id="@+id/nav_friends"
            android:icon="@drawable/nav_friends"
            android:title="@string/nav_friend"/>
        <item
            android:id="@+id/nav_location"
            android:icon="@drawable/nav_location"
            android:title="@string/nav_location"/>
        <item
            android:id="@+id/nav_mail"
            android:icon="@drawable/nav_mail"
            android:title="@string/nav_mail"/>
        <item
            android:id="@+id/nav_task"
            android:icon="@drawable/nav_task"
            android:title="@string/nav_task"/>

    </group>

</menu>
  • 在layout中新建一个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:id="@+id/icon_image"
		        android:layout_width="70dp"
		        android:layout_height="70dp"
		        android:src="@drawable/header"
		        android:layout_centerInParent="true"/>

		    <TextView
		        android:id="@+id/mail"
		        android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:layout_alignParentBottom="true"
		        android:text="@string/mail"
		        android:textColor="#fff"
		        android:textSize="14sp"/>

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

</RelativeLayout>
  • 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">
		    <!--  该控件用于作为主屏幕中显示的内容,以及toolBar  -->
		    <FrameLayout
		        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="?attr/colorPrimary"
		            android:theme="@style/ThemeOverlay.AppCompat.DayNight.ActionBar"
		            app:popupTheme="@style/ThemeOverlay.AppCompat.DayNight"/>
		    </FrameLayout>
		    <!--  layout_gravity指定了菜单所处的方向,且必须指定
		            如果是left就在左边,right就在右边,start表示跟随系统语言方向,从左往右就在左边-->
		    <com.google.android.material.navigation.NavigationView
		        android:id="@+id/nav_view"
		        android:layout_width="match_parent"
		        android:layout_height="match_parent"
		        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 = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //得到DrawerLayout实例
        mDrawerLayout = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);

        //得到ActionBar实例,具体实现由ToolBar来完成
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            //让导航按钮显示出来
            actionBar.setDisplayHomeAsUpEnabled(true);
            //设置一个导航按钮图标,将图片传进去
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        }

        navigationView.setCheckedItem(R.id.nav_call);
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                mDrawerLayout.closeDrawers();
                //Toast.makeText(MainActivity.this,"This is nav",Toast.LENGTH_SHORT).show();
                return true;
            }
        });

    }

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

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
                //HomeAsUp的图标的id永远是这一个
            case android.R.id.home:
                //调用该方法将菜单展示出来,传入的参数是Gravity参数
                mDrawerLayout.openDrawer(GravityCompat.START);
                break;
            case R.id.backup:
                Toast.makeText(this,"You clicked backup",Toast.LENGTH_SHORT).show();
                //能响应点击事件
                startActivity(new Intent(this,MainActivity.class));
                break;
            case R.id.delete:
                Toast.makeText(this,"You clicked delete",Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"You clicked settings",Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }
}

悬浮按钮FloatingActionButton

  • activity_main.xml
<?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:layout_width="match_parent"
		    android:layout_height="match_parent">
		    <!--  该控件用于作为主屏幕中显示的内容,以及toolBar  -->
		    <FrameLayout
		        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="?attr/colorPrimary"
		            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
		            app:popupTheme="@style/ThemeOverlay.AppCompat.DayNight"/>

		        <!--  替换系统背景颜色android:backgroundTint="#fff"
		                  替换系统背景颜色和系统边框颜色app:backgroundTint="#009688"
		                  替换图标默认颜色android:tint="#fff"-->
		        <com.google.android.material.floatingactionbutton.FloatingActionButton
		            android:id="@+id/fab"
		            android:tint="#fff"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_gravity="bottom|end"
		            android:layout_margin="16dp"
		            android:src="@drawable/ic_done"
		            android:elevation="8dp"
		            android:onClick="fabClick"
		            app:backgroundTint="#009688" />

		    </FrameLayout>
		    <!--  layout_gravity指定了菜单所处的方向,且必须指定
		            如果是left就在左边,right就在右边,start表示跟随系统语言方向,从左往右就在左边
		            通过menu和headerLayout属性将刚才准备好的布局添加进去-->
		    <com.google.android.material.navigation.NavigationView
		        android:id="@+id/nav_view"
		        android:layout_width="match_parent"
		        android:layout_height="match_parent"
		        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 = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //得到DrawerLayout实例
        mDrawerLayout = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);

        //得到ActionBar实例,具体实现由ToolBar来完成
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            //让导航按钮显示出来
            actionBar.setDisplayHomeAsUpEnabled(true);
            //设置一个导航按钮图标,将图片传进去
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        }

        navigationView.setCheckedItem(R.id.nav_call);
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                mDrawerLayout.closeDrawers();
                //Toast.makeText(MainActivity.this,"This is nav",Toast.LENGTH_SHORT).show();
                return true;
            }
        });

    }

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

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
                //HomeAsUp的图标的id永远是这一个
            case android.R.id.home:
                //调用该方法将菜单展示出来,传入的参数是Gravity参数
                mDrawerLayout.openDrawer(GravityCompat.START);
                break;
            case R.id.backup:
                Toast.makeText(this,"You clicked backup",Toast.LENGTH_SHORT).show();
                //能响应点击事件
                startActivity(new Intent(this,MainActivity.class));
                break;
            case R.id.delete:
                Toast.makeText(this,"You clicked delete",Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"You clicked settings",Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }

    public void fabClick(View view) {

        Toast.makeText(this,"You clicked FloatingActionButton",Toast.LENGTH_SHORT).show();

    }
}

可交互提示SnackBar

  • MainActivity
public void fabClick(View view) {

    Snackbar.make(view,"Data deleted",Snackbar.LENGTH_INDEFINITE)
        .setAction("Undo", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"Data Restored",Toast.LENGTH_SHORT).show();
            }
        }).show();
    //Toast.makeText(this,"You clicked FloatingActionButton",Toast.LENGTH_SHORT).show();

}

布局CoordinatorLayout

是加强版的FrameLayout,可以监听其所有子控件的各种事件,自动帮我们做出合理的响应

它会监听到弹出事件然后将你的控件合理的移动

<androidx.coordinatorlayout.widget.CoordinatorLayout
	        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="?attr/colorPrimary"
	            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
	            app:popupTheme="@style/ThemeOverlay.AppCompat.DayNight"/>

	        <!--  替换系统背景颜色android:backgroundTint="#fff"
	                  替换系统背景颜色和系统边框颜色app:backgroundTint="#009688"
	                  替换图标默认颜色android:tint="#fff"-->
	        <com.google.android.material.floatingactionbutton.FloatingActionButton
	            android:id="@+id/fab"
	            android:tint="#fff"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:layout_gravity="bottom|end"
	            android:layout_margin="16dp"
	            android:src="@drawable/ic_done"
	            android:elevation="8dp"
	            android:onClick="fabClick"
	            app:backgroundTint="#009688" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

卡片式布局CardView

  • activity_main.xml
<?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"
		    xmlns:tools="http://schemas.android.com/tools"
		    android:id="@+id/drawer_layout"
		    android:layout_width="match_parent"
		    android:layout_height="match_parent">

		    <!--  该控件用于作为主屏幕中显示的内容,以及toolBar  -->
		    <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">

		            <!--  layout_scrollFlags属性中,scroll表示当RecyclerView向上滚动的时候,ToolBar会跟着一起向上滚动并实现隐藏
		                    enterAlways表示当向下滚动时,会一起向下滚动并显示
		                    snap表示当ToolBar还没有完全显示或隐藏的时候,会根据当前滚动的距离,自动选择是隐藏还是显示-->
		            <androidx.appcompat.widget.Toolbar
		                android:id="@+id/toolbar"
		                android:layout_width="match_parent"
		                android:layout_height="?attr/actionBarSize"
		                android:background="?attr/colorPrimary"
		                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
		                app:popupTheme="@style/ThemeOverlay.AppCompat.DayNight"
		                app:layout_scrollFlags="scroll|enterAlways|snap"/>

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

		        <!--实现下拉刷新-->
		        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
		            android:id="@+id/swipe_refresh"
		            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"
		                app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

		        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

		        <!--  替换系统背景颜色android:backgroundTint="#fff"
		                  替换系统背景颜色和系统边框颜色app:backgroundTint="#009688"
		                  替换图标默认颜色android:tint="#fff"-->
		        <com.google.android.material.floatingactionbutton.FloatingActionButton
		            android:id="@+id/fab"
		            android:tint="#fff"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_gravity="bottom|end"
		            android:layout_margin="16dp"
		            android:src="@drawable/ic_done"
		            android:elevation="8dp"
		            android:onClick="fabClick"
		            app:backgroundTint="#009688"
		            tools:targetApi="lollipop" />

		    </androidx.coordinatorlayout.widget.CoordinatorLayout>

		    <!--  layout_gravity指定了菜单所处的方向,且必须指定
		            如果是left就在左边,right就在右边,start表示跟随系统语言方向,从左往右就在左边
		            通过menu和headerLayout属性将刚才准备好的布局添加进去-->
		    <com.google.android.material.navigation.NavigationView
		        android:id="@+id/nav_view"
		        android:layout_width="match_parent"
		        android:layout_height="match_parent"
		        android:layout_gravity="start"
		        app:menu="@menu/nav_menu"
		        app:headerLayout="@layout/nav_header"/>

</androidx.drawerlayout.widget.DrawerLayout>
  • fruit_item.xml
<?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"
		    xmlns:tools="http://schemas.android.com/tools"
		    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">

		        <!--  指定图片的缩放模式,按原比例,超出部分会被剪裁掉android:scaleType="centerCrop"  -->
		        <ImageView
		            android:id="@+id/fruit_image"
		            android:layout_width="match_parent"
		            android:layout_height="100dp"
		            android:scaleType="centerCrop" />

		        <TextView
		            android:id="@+id/fruit_name"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_gravity="center_horizontal"
		            android:layout_margin="5dp"
		            android:textSize="16sp"/>
		    </LinearLayout>
</androidx.cardview.widget.CardView>
  • Fruit.java
/**
* Description
* <p>
* 用于封装水果的信息
* @author qricis on 2020/9/2 9:17
* @version 1.0.0
*/
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;
    }

}
  • FruitAdapter.java
/**
* Description
* <p>
* RecyclerView的适配器,继承自RecyclerView.Adapter,泛型指定为FruitAdapter.ViewHolder
* @author qricis on 2020/9/2 10:07
* @version 1.0.0
*/
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {

    private Context mContext;

    private List<Fruit> mFruitList;

    /**
		     * 寻找定义fruit_item的控件
		     * */
    static class ViewHolder extends RecyclerView.ViewHolder {

        private CardView mCardView;
        private ImageView fruitImage;
        private TextView fruitName;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            mCardView = (CardView) itemView;
            fruitImage = itemView.findViewById(R.id.fruit_image);
            fruitName = itemView.findViewById(R.id.fruit_name);
        }
    }

    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    /**
		     * 返回一个ViewHolder(fruit_item),将recyclerView的视图返回
		     * */
    @NonNull
    @Override
    public 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 ViewHolder holder, int position) {

        Fruit fruit = mFruitList.get(position);
        holder.fruitName.setText(fruit.getName());

        //传入一个context/fragment/activity参数,然后加载图片,可以是URL地址/本地路径/资源id,然后将图片设置到某一个imageView中
        //不需要担心内存溢出
        Glide.with(mContext).load(fruit.getImageId()).into(holder.fruitImage);

    }

    @Override
    public int getItemCount() {
        return mFruitList.size();
    }
}
  • MainActivity.java
public class MainActivity extends AppCompatActivity {

    private DrawerLayout mDrawerLayout;

    private Fruit[] mFruits = {new Fruit("Apple",R.drawable.apple),new Fruit("Cherry",R.drawable.cherry),
                               new Fruit("Orange",R.drawable.orange),new Fruit("Pear",R.drawable.pear),
                               new Fruit("Pineapple",R.drawable.pineapple),new Fruit("Strawberry",R.drawable.strawberry),
                               new Fruit("Watermelon",R.drawable.watermelon),new Fruit("Mango",R.drawable.mango),
                               new Fruit("Banana",R.drawable.banana),new Fruit("Grape",R.drawable.grape)};

    private List<Fruit> mFruitList = new ArrayList<>();

    private FruitAdapter mFruitAdapter;

    private SwipeRefreshLayout mSwipeRefreshLayout;

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

        // 得到DrawerLayout实例
        mDrawerLayout = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);

        // 得到ActionBar实例,具体实现由ToolBar来完成
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            // 让导航按钮显示出来
            actionBar.setDisplayHomeAsUpEnabled(true);
            // 设置一个导航按钮图标,将图片传进去
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        }

        navigationView.setCheckedItem(R.id.nav_call);
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                mDrawerLayout.closeDrawers();
                //Toast.makeText(MainActivity.this,"This is nav",Toast.LENGTH_SHORT).show();
                return true;
            }
        });

        // 实现RecyclerView
        // 初始化List<Fruit>数组
        initFruits();
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        // 定义布局方式 LinearLayoutManager直接是线性布局
        //LinearLayoutManager layoutManager = new LinearLayoutManager(this);

        // 瀑布流布局,实现交错式布局,第一个参数是列数,第二个参数是显示方向
        //StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
        // 不设置的话,图片闪烁错位,有可能有整列错位的情况。
        //layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);

        // GridLayoutManager是网格布局 第一个参数为context,第二个参数为列数
        GridLayoutManager layoutManager = new GridLayoutManager(this,2);
        recyclerView.setLayoutManager(layoutManager);
        mFruitAdapter = new FruitAdapter(mFruitList);
        recyclerView.setAdapter(mFruitAdapter);

        // 下拉刷新
        mSwipeRefreshLayout = findViewById(R.id.swipe_refresh);
        mSwipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.colorPrimary));
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshFruit();
            }

        });
    }

    /**
	* 下拉刷新实现
	* */
    private void refreshFruit() {

        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();
                        mFruitAdapter.notifyDataSetChanged();
                        mSwipeRefreshLayout.setRefreshing(false);
                    }
                });
            }
        }).start();

    }

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

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

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
                // HomeAsUp的图标的id永远是这一个
            case android.R.id.home:
                // 调用该方法将菜单展示出来,传入的参数是Gravity参数
                mDrawerLayout.openDrawer(GravityCompat.START);
                break;
            case R.id.backup:
                Toast.makeText(this,"You clicked backup",Toast.LENGTH_SHORT).show();
                // 能响应点击事件
                startActivity(new Intent(this,MainActivity.class));
                break;
            case R.id.delete:
                Toast.makeText(this,"You clicked delete",Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"You clicked settings",Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }

    public void fabClick(View view) {

        Snackbar.make(view,"Data deleted",Snackbar.LENGTH_LONG)
            .setAction("Undo", new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(MainActivity.this,"Data Restored",Toast.LENGTH_SHORT).show();
                }
            }).show();
        //Toast.makeText(this,"You clicked FloatingActionButton",Toast.LENGTH_SHORT).show();

    }
}

可折叠式标题栏CollapsingToolBarLayout

  • activity_fruit
<?xml version="1.0" encoding="utf-8"?>
		<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">

		        <!-- 设定高级的标题栏属性
		                contentScrim用于指定其趋于折叠状态以及折叠之后的背景色
		                layout_scrollFlags属性中,scroll表示会随着内容详情的滚动而滚动,exitUntilCollapsed表示当其随着滚动完成折叠之后就保留在界面上,不再移出屏幕-->
		        <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">

		            <!-- layout_collapseMode属性用于指定当前控件在其折叠过程中的折叠模式
		                    parallax表示在折叠过程中产生一定的错位偏移,pin表示在折叠过程中位置始终保持不变-->
		            <ImageView
		                android:id="@+id/fruit_image_view"
		                android:layout_width="match_parent"
		                android:layout_height="match_parent"
		                android:scaleType="centerCrop"
		                app:layout_collapseMode="parallax"
		                android:contentDescription="@string/this_is_a_pics" />

		            <androidx.appcompat.widget.Toolbar
		                android:id="@+id/toolbar"
		                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>

		    <!-- 内容详情部分实现 -->
		    <!-- ScrollView实现滚动的方式来查看屏幕以外的数据
		           NestedScrollView增加了实现嵌套响应滚动事件的功能 -->
		    <androidx.core.widget.NestedScrollView
		        android:layout_width="match_parent"
		        android:layout_height="match_parent">

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

		            <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="34dp"
		                app:cardCornerRadius="4dp">

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

		            </androidx.cardview.widget.CardView>
		            
		        </LinearLayout>

		    </androidx.core.widget.NestedScrollView>
		    
		    <!-- 制作评论的悬浮图标 -->
		    <!-- layout_anchor指定了一个锚点,我们指定了AppBarLayout,该悬浮按钮就会出现在标题栏区域内 -->
		    <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>
  • FruitActivity
/**
* Description
* <p>
*
* @author qricis on 2020/9/2 14:45
* @version 1.0.0
*/
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(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fruit);

        Intent intent = getIntent();

        String fruitName = intent.getStringExtra(FRUIT_NAME);
        int fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID,0);

        Toolbar toolbar = findViewById(R.id.toolbar);
        CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
        ImageView fruitImageView = findViewById(R.id.fruit_image_view);
        TextView fruitContentText = findViewById(R.id.fruit_name_view);

        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        collapsingToolbarLayout.setTitle(fruitName);
        Glide.with(this).load(fruitImageId).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) {

        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}
  • FruitAdapter
/**
 * 返回一个ViewHolder(fruit_item),将recyclerView的视图返回
 * */
@NonNull
@Override
public 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);

    // 给CardView注册一个点击事件监听器
    final ViewHolder holder = new ViewHolder(view);
    holder.mCardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            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;
}

可系统状态栏隐藏

  • styles-v21
<?xml version="1.0" encoding="utf-8"?>
<resources>

		    <!-- 将状态栏的颜色设置成透明色 -->
		    <style name="FruitActivityTheme" parent="AppTheme">
		        <item name="android:statusBarColor">@android:color/transparent</item>
		    </style>

</resources>
  • 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>
  • Manifest
<activity android:name=".activity.FruitActivity"
            android:theme="@style/FruitActivityTheme"/>
  • activity_fruit
<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:layout_height="250dp"
		        android:fitsSystemWindows="true">

		        <!-- 设定高级的标题栏属性
		                contentScrim用于指定其趋于折叠状态以及折叠之后的背景色
		                layout_scrollFlags属性中,scroll表示会随着内容详情的滚动而滚动,exitUntilCollapsed表示当其随着滚动完成折叠之后就保留在界面上,不再移出屏幕-->
		        <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"
		            android:fitsSystemWindows="true">

		            <!-- layout_collapseMode属性用于指定当前控件在其折叠过程中的折叠模式
		                    parallax表示在折叠过程中产生一定的错位偏移,pin表示在折叠过程中位置始终保持不变
		                    android:fitsSystemWindows="true"借助这一属性,让背景图和状态栏融合,且必须将其所有父布局都设成true,除此之外,需要在styles中将状态栏设定为透明色-->
		            <ImageView
		                android:id="@+id/fruit_image_view"
		                android:layout_width="match_parent"
		                android:layout_height="match_parent"
		                android:scaleType="centerCrop"
		                app:layout_collapseMode="parallax"
		                android:contentDescription="@string/this_is_a_pics"
		                android:fitsSystemWindows="true"/>

		            <androidx.appcompat.widget.Toolbar
		                android:id="@+id/toolbar"
		                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>

		    <!-- 内容详情部分实现 -->
		    <!-- ScrollView实现滚动的方式来查看屏幕以外的数据
		           NestedScrollView增加了实现嵌套响应滚动事件的功能
		           layout_behavior指定了一个布局行为,使得不挡住标题栏-->
		    <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="wrap_content">

		            <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="34dp"
		                app:cardCornerRadius="4dp">

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

		            </androidx.cardview.widget.CardView>

		        </LinearLayout>

		    </androidx.core.widget.NestedScrollView>

		    <!-- 制作评论的悬浮图标 -->
		    <!-- layout_anchor指定了一个锚点,我们指定了AppBarLayout,该悬浮按钮就会出现在标题栏区域内 -->
		    <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>

完整代码展示

https://github.com/qricis/DoSomeAndroidTest/tree/main/MaterialTest

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值