Android MaterialDesign的用法

入门代码demo在CSDN资源上面

一.Toolbar(切记切记在android5.0以上)

1.使用Toolbar替换ActionBar,创建项目是默认的actionbar,我们需要一个不带actionbar。
 1).默认的actionbar:

>
    <!-- Base application theme. -->
    
>

2).修改后为不带actionbar 可以修改为Theme.AppCompat.Light.NoActionBar和Theme.AppCompat.NoActionBar两种属性前者是淡色主题,后者是深色,我们一般使用淡色主题。

>
    <!-- Base application theme. --><!--淡色的toobar-->
    
>

2.style中的文件

>
    <!-- Base application theme. --><!--设置为不要actionbar-->
    

    <!--设置点击toolbar显示在下方-->
    
>

3.在res下面创建menu的文件夹,然后创建对应的Menu resourcefile文件
 选择3个图片,用于显示
Android MaterialDesign的用法_第1张图片

<?xml version="1.0" encoding="utf-8"?>
:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
        <!--app:showAsAction="always"设置显示的位置
        always在toolbar中显示
        ifRoom 看屏幕是否足够
        never显示图标
    .-->
    
   :icon="@drawable/alter_delete"
        android:id="@+id/delete"
       app:showAsAction="ifRoom"
        android:title="删除" />
    :icon="@drawable/setting"
        android:id="@+id/settings"
        app:showAsAction="never"
        android:title="设置" />
>

在这里插入图片描述
4.活动中的方法,引入toolbar以及设置点击事件

package com.example.materialdesign;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

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);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);//标题栏带返回按钮
    }

    //动态加载标题栏的toolbar
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbarl,menu);
        return super.onCreateOptionsMenu(menu);
    }

    //多个toobar选中是点的哪一个
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case R.id.backup:
                Toast.makeText(this,"点击了返回",Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(this,"点击了删除",Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"点击了设置",Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }
}
    //toolbar中显示图标
    @SuppressLint("RestrictedApi")
    @Override
    protected boolean onPrepareOptionsPanel(View view, Menu menu) {
        if (menu != null) {
            if (menu.getClass() == MenuBuilder.class) {
                try {
                    //利用反射获取私有方法
                    Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return super.onPrepareOptionsPanel(view, menu);
    }

5.layout文件

    :id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ToolBarPopupThem"
        tools:ignore="MissingConstraints">>

二.侧边栏DrawerLayout

1.加粗样式1.layout文件中:

DrawerLayout内部第一个控件为显示界面,第二个控件为滑动弹出,并且第一个控件设置的是标题,所以需要一个控件来承载,第二个控件一定要记得android:layout_gravity="start"属性,设置左滑动还是有滑动显示

<?xml version="1.0" encoding="utf-8"?>
: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="match_parent"
    tools:context=".MainActivity">
    <!--滑动侧边栏-->
    
        
            
            
        
        
        
    
>

2.但是用户可能不知道左侧有东西,所以我们可以通过在标题栏上设置一个按钮。
活动中调用

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar=findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        //getSupportActionBar().setDisplayHomeAsUpEnabled(true);//标题栏带返回按钮

        //滑动菜单栏可以通过标题栏左边打开
        drawerLayout=findViewById(R.id.drawer_laout);
        ActionBar actionBar=getSupportActionBar();
        if(actionBar!=null){
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeAsUpIndicator(R.drawable.left_menu);
        }
}

   //多个toobar选中是点的哪一个
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case R.id.backup:
                Toast.makeText(this,"点击了返回",Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(this,"点击了删除",Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"点击了设置",Toast.LENGTH_SHORT).show();
                break;
                //标题栏左边ID永远为android.R.id.home
            case android.R.id.home:
                drawerLayout.openDrawer(GravityCompat.START);//显示隐藏的内容
                break;
        }
        return true;
    }

三.NavigationView优化侧边栏

1.引入两个库文件

    //优化侧边栏的库
    implementation 'com.android.support:design:28.0.0'
    //对图片进行处理
    implementation 'de.hdodenhof:circleimageview:2.1.0'

2.menu下添加xml文件
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
:android="http://schemas.android.com/apk/res/android">
    :checkableBehavior="single">
        :id="@+id/nav_call"
            android:icon="@drawable/call"
            android:title="Call">>
        :id="@+id/nav_friends"
            android:icon="@drawable/friends_first_proccess"
            android:title="Friends">>
        :id="@+id/nav_location"
            android:icon="@drawable/location"
            android:title="Location">>
        :id="@+id/nav_mail"
            android:icon="@drawable/mail_fill"
            android:title="Call">>
        :id="@+id/nav_task"
            android:icon="@drawable/tasks"
            android:title="Tasks">>
    >
>

3.header的xml文件

<?xml version="1.0" encoding="utf-8"?>
:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="180dp"
    android:background="@color/colorPrimary">
    :id="@+id/icon_image"
        android:src="@drawable/live2d"
        android:layout_centerInParent="true"
        android:layout_width="70dp"
        android:layout_height="70dp">>
    :layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/mail"
        android:layout_alignParentBottom="true"
        android:textColor="#FFF"
        android:textSize="14sp"
        android:text="[email protected]">>
    :layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/username"
        android:layout_above="@+id/mail"
        android:textColor="#FFF"
        android:textSize="14sp"
        android:text="王长印">>
>

4.主布局文件引入

<?xml version="1.0" encoding="utf-8"?>
: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="match_parent"
    tools:context=".MainActivity">
    <!--滑动侧边栏-->
    
        
            
            
        


        :id="@+id/nav_view"
            android:layout_gravity="start"
            app:menu="@menu/nav_menu"
            app:headerLayout="@layout/nav_header"
            android:layout_width="match_parent"
            android:layout_height="match_parent">>
    >
>

5.侧边栏的监听事件

        final NavigationView navigationView=findViewById(R.id.nav_view);
        navigationView.setCheckedItem(R.id.nav_call);//打开侧边栏默认选中菜单
        //菜单栏的监听事件
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                navigationView.setCheckedItem(menuItem.getItemId());//点击的菜单设置为选中
                Toast.makeText(MainActivity.this,"点击了"+menuItem.getTitle(),Toast.LENGTH_SHORT).show();
                return false;
            }
        });

四.FloatingActionBar悬浮框(其实就是按钮,不过是悬浮的)

1.layout文件

<!--悬浮框-->
            

2.活动(activit)中的监听事件

        //悬浮框的监听
        FloatingActionButton floatingActionButton= findViewById(R.id.float_ok);
        floatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"点击了悬浮框",Toast.LENGTH_SHORT).show();
            }
        });

五.Snackbar(提示框,类似于Toast,只不过可以让用户点击)

                //Snackbar的用法
                Snackbar.make(view,"This is 悬浮框",Snackbar.LENGTH_SHORT)
                        .setAction("Sure", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(MainActivity.this,"点击了悬浮框",Toast.LENGTH_SHORT).show();
                            }
                        })
                        .show();

六.CoordinatorLayout(与Fragment类似,多一个可以子控件得到合理的相应)

由于使用了上面的Snackbar,悬浮框会被挡住,我们可以借助CoordinatorLayout来让悬浮框向上移动,提示一结束又移动下来。
1.用法:

        :layout_width="match_parent"
            android:layout_height="match_parent">
            <!--标题-->
            
            
            
        >

七.卡片式布局(CardView)
1.cardView配合RecycleView使用。
2.引入依赖。

    implementation 'androidx.recyclerview:recyclerview:1.1.0'//引入recyclerview
    implementation 'androidx.cardview:cardview:1.0.0' //卡片式布局
    implementation 'com.github.bumptech.glide:glide:3.7.0' //对图片加载

3.main的layout文件引入recyclerview:recyclerview

        :layout_width="match_parent"
            android:layout_height="match_parent">
            <!--标题-->
            

            <!--引入RecyclerView-->
            

            <!--悬浮框-->
            
        >

4.一个RecyclerView的item类

package com.example.materialdesign.recycle;

public class Fruit {
    private String name;
    private int imageId;

    public Fruit() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getImageId() {
        return imageId;
    }

    public void setImageId(int imageId) {
        this.imageId = imageId;
    }
}

5…item 的layout文件

<?xml version="1.0" encoding="utf-8"?>
<!--这个要在最外层-->
    
        
            
            
        
    

6.对应的适配器.

package com.example.materialdesign.recycle;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.example.materialdesign.R;

import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter> {
    private Context mContext;
    private List> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder{
        CardView cardView;
        ImageView imageView;
        TextView textView;
        public ViewHolder(@NonNull View view) {
            super(view);
            cardView=(CardView)view;
            imageView=view.findViewById(R.id.fruit_image);
            textView=view.findViewById(R.id.fruit_name);
        }
    }

    public FruitAdapter(List> list){
        mFruitList=list;
    }

    @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_ite, parent, false);
        return new ViewHolder(view);
    }

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

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

}

7.活动中:

//引入数据
    private Fruit[] fruits={new Fruit("apple",R.drawable.live2d),
            new Fruit("Orange",R.drawable.live2d),
            new Fruit("Banana",R.drawable.live2d),
            new Fruit("Watermelon",R.drawable.live2d),
            new Fruit("Pear",R.drawable.live2d),
            new Fruit("Cherry",R.drawable.live2d)
    };
    private List> fruitList=new ArrayList<>();
    private FruitAdapter adapter;


        //卡片式布局与RecyclerView
        initFruit();
        RecyclerView recyclerView=findViewById(R.id.recycle_view);
        GridLayoutManager layoutManager=new GridLayoutManager(this,2);
        recyclerView.setLayoutManager(layoutManager);
        adapter=new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);

    private void initFruit() {
        fruitList.clear();
        //随机生成50个
        for(int i=0;i<50;i++){
            Random random=new Random();
            int index=random.nextInt(fruits.length);
            fruitList.add(fruits[index]);
        }
    }

8.存在的问题:
这样会把标题栏给遮住了,所以可以通过下面来解决

七.AppBarLayout

出现把标题栏遮挡的原因:
由于RecyclerView的外层是CoordinatorLayout,CoordinatorLayout是一个加强版的Frament,标题栏和RecyclerView所以会出现覆盖现象
1.把标题栏放到AppBarLayout中

            :layout_width="match_parent"
                android:layout_height="wrap_content">
                <!--标题-->
                
            >

2.RecyclerView加一个属性:

 <!--引入RecyclerView-->
            

3.实现向下滚动标题栏隐藏
其实在RecyclerView滚动的时候已经把滚动时间通知给AppBarLayout
只需要加入app:layout_scrollFlags="scroll|enterAlways|snap"属性

        :layout_width="match_parent"
            android:layout_height="match_parent">
            :layout_width="match_parent"
                android:layout_height="wrap_content">
                <!--标题-->
                
            >

八.下拉刷新(SwipeRefreshLayout)

1.在哪个控件需要下拉刷新就在外层包裹
app:layout_behavior="@string/appbar_scrolling_view_behavior"属性要移动SwipeRefreshLayout来,因为RecyclerView是子控件了,这是上面放置标题栏被遮挡的属性。

            <!---下拉刷新-->
            
                
                
            

2.活动中刷新的事件

        //刷新
        swipeRefresh=findViewById(R.id.swipe_refresh);
        swipeRefresh.setColorSchemeColors(R.color.colorPrimary);//设置默认颜色
        swipeRefresh.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() {
                        initFruit();//初始化数据
                        adapter.notifyDataSetChanged();//通知适配器数据发生变化
                        swipeRefresh.setRefreshing(false);//隐藏刷新
                    }
                });
            }
        }).start();
    }

九.可折叠的标题栏(CollapsingToolbarLayout)

1.CollapsingToolbarLayout必须要有AppBarLayout,而AppBarLayout又必须要CoordinatorLayout。
新建布局文件 (activit_fruit)
NestedScrollView是可以嵌套滚动事件的

<?xml version="1.0" encoding="utf-8"?>
<!--合适的响应位置-->
:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:fitsSystemWindows="true">
    <!--让标题栏显示出来 由于CoordinatorLayout的原因,所以需要AppBarLayout-->
    
        
        
            
            
        
    

    <!--水果内容
    app:layout_behavior="@string/appbar_scrolling_view_behavior"显示标题-->
    
        
        
            
                
            
        
    
    
    
>

2.新建活动FruitActivity

package com.example.materialdesign;

import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.google.android.material.appbar.CollapsingToolbarLayout;

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 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 fruitTextView=findViewById(R.id.fruit_content_text);
        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);//显示内容
        fruitTextView.setText(fruitContent);
    }
    //模拟内容
    private String generateFruitContent(String fruitName) {
        StringBuilder builder=new StringBuilder();
        for(int i=0;i<500;i++){
            builder.append(fruitName);
        }
        return builder.toString();
    }

    //标题栏的监听事件
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

3.之前的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_ite, parent, false);

        //点击跳转
        final ViewHolder holder=new ViewHolder(view);
        holder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               int positon=holder.getAdapterPosition();
               Fruit fruit=mFruitList.get(positon);
                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;
    }

十.充分利用系统状态栏(图片现显示在状态栏)

1.在需要图片显示在状态栏加上属性 android:fitsSystemWindows="true"以及其分容器都要加上
2.res下面创建一个values-v21
由于5.0之前没有透明属性,所以新建values-v21的文件夹
3.在values新建styles.xml

<?xml version="1.0" encoding="utf-8"?>
>
    <!--android5.0以后特有的属性,声明状态栏为透明-->
    
>

4.在原始的values →styles.xml里面加上

    <!--状态栏透明-->