1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Android 学习之《第一行代码》第二版 笔记(二十三)Material Design 实战 —— 卡片式布局

Android 学习之《第一行代码》第二版 笔记(二十三)Material Design 实战 —— 卡片式布局

时间:2024-07-21 19:58:31

相关推荐

Android 学习之《第一行代码》第二版 笔记(二十三)Material Design 实战 —— 卡片式布局

实现基础:

Android 学习之《第一行代码》第二版 笔记(二十二)Material Design 实战 —— 悬浮按钮和可交互提示

卡片式布局

卡片式布局是 Materials Design 中提出的一个新的概念,可以让页面中的元素看起来就像在卡片中一样,并且拥有圆角和投影,实际上也是一个FrameLayout

1. 效果图

效果说明:未使用AppBarLayout时,RecyclerView 会把Toolbar给遮挡住,因为:CoordinatorLayout 就是一个加强版的 FrameLayout,里面的所有控件在不进行明确定位的情况下,默认都会摆在布局左上角,从而产生遮挡现象。使用 AppBarLayout 后解决此问题,而且向上滚动 RecyclerView 时,Toolbar 消失;向下滚动 RecyclerView Toolbar 出现。

A.)CardView 未使用AppBarLayout

B.)CardView 使用AppBarLayout

2. 代码

A.)添加库依赖 (app/build.gradle)

在 dependencies 里面添加,版本号啥的根据实际情况调整

implementation 'com.android.support:recyclerview-v7:26.1.0'implementation 'com.android.support:cardview-v7:26.1.0'implementation 'com.github.bumptech.glide:glide:3.7.0'

B.)activity_main.xml

<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.DrawerLayout xmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"android:id="@+id/drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><!--使用AppBarLayout解决覆盖问题第一步:将Toolbar嵌套到AppBarLayout中;第二步:给RecyclerView指定一个布局行为--><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><android.support.v7.widget.Toolbarandroid: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.Light"app:layout_scrollFlags="scroll|enterAlways|snap"><!--当AppBarLayout接收到滚动事件的时候,它内部的子控件可以指定如何去影响这些事件。app:layout_scrollFlags属性:scroll表示当RecyclerView向上滚动时,Toolbar会跟着向上滚动并实现隐藏enterAlways表示当RecyclerView向下滚动时,Toolbar会跟着向下滚动并重新显示snap表示当Toolbar还没有完全隐藏或显示时,会根据当前滚动的距离,自动选择隐藏还是显示--></android.support.v7.widget.Toolbar></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerViewandroid:id="@+id/recycler_view"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"><!--使用layout_behavior指定布局行为--></android.support.v7.widget.RecyclerView><!--app:elevation="8dp"设置悬浮按钮的悬浮高度为8dp,高度值越大,投影范围越大,投影效果越淡--><android.support.design.widget.FloatingActionButtonandroid:id="@+id/fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|end"android:layout_margin="16dp"android:src="@drawable/ic_done"app:elevation="8dp"/></android.support.design.widget.CoordinatorLayout><android.support.design.widget.NavigationViewandroid: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"></android.support.design.widget.NavigationView></android.support.v4.widget.DrawerLayout>

C.)水果实体类(Fruit.java)

public class Fruit {private String name; //水果名字private int imageId; //水果对应资源idpublic Fruit(String name,int imageId){this.name = name;this.imageId = imageId;}public String getName() {return name;}public int getImageId() {return imageId;}}

D.)为RecyclerView的子项指定一个自定义布局(layout/fruit_item.xml)

<?xml version="1.0" encoding="utf-8"?><android.support.v7.widget.CardViewxmlns:android="/apk/res/android"xmlns:app = "/apk/res-auto"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="5dp"app:cardCornerRadius="4dp"><!--app:cardCornerRadius="4dp"指定卡片圆角的弧度,数值越大弧度越大--><!--app:elevation 属性可以指定卡片高度,高度值越大,投影范围越大,投影效果越淡--><!--由于CardView是一个FrameLayout没有什么方便的定位方式,所以在其中嵌套一个LinearLayout--><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"><!--用于显示水果图片,scaleType属性指定图片缩放模式,值centerCrop让图片保持原有比例填满整个ImageView,并将超出屏幕的部分裁减掉--><ImageViewandroid:id="@+id/fruit_image"android:layout_width="match_parent"android:layout_height="100dp"android:scaleType="centerCrop" /><!--用于显示水果名称--><TextViewandroid: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></android.support.v7.widget.CardView>

E.)为RecyclerView 准备一个适配器(FruitAdapter.java)

import android.content.Context;import android.support.v7.widget.CardView;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import com.bumptech.glide.Glide;import java.util.List;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;//静态内部类的构造函数,参数view通常就是RecyclerView子项的最外层布局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;}//用于告诉RecyclerView一共有多少子项,直接返回数据源的长度即可@Overridepublic int getItemCount() {return mFruitList.size();}//用于对RecyclerView子项的数据进行赋值,会在每个子项被滚动到屏幕内的时候执行。@Overridepublic void onBindViewHolder(FruitAdapter.ViewHolder holder, int position) {Fruit fruit = mFruitList.get(position);holder.fruitName.setText(fruit.getName());//使用Glide加载水果图片 Glide在内部有许多复杂的逻辑结构,包括图片压缩,防止内存溢出//Glide 用法://首先调用Glide的with()方法,传入一个Context/Activity/Fragment参数//然后调用load()方法加载图片,传入一个URL地址或者本地路径或一个资源id//最后调用into()方法设置到具体某一个ImageView即可Glide.with(mContext).load(fruit.getImageId()).into(holder.fruitImage);}//用于创建ViewHolder实例@Overridepublic FruitAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {if(mContext == null){mContext = parent.getContext();}View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);ViewHolder holder = new ViewHolder(view);return holder;}}

F.)MainActivity.java

import android.support.annotation.NonNull;import android.support.design.widget.FloatingActionButton;import android.support.design.widget.NavigationView;import android.support.design.widget.Snackbar;import android.support.v4.view.GravityCompat;import android.support.v4.widget.DrawerLayout;import android.support.v7.app.ActionBar;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.Toolbar;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.Toast;import java.util.ArrayList;import java.util.List;import java.util.Random;public class MainActivity extends AppCompatActivity {private DrawerLayout mDrawerLayout;private Fruit[] fruits = {new Fruit("苹果",R.drawable.apple),new Fruit("香蕉",R.drawable.banana),new Fruit("橘子",R.drawable.orange),new Fruit("西瓜",R.drawable.watermelon),new Fruit("梨",R.drawable.pear),new Fruit("葡萄",R.drawable.grape),new Fruit("菠萝",R.drawable.pineapple),new Fruit("草莓",R.drawable.strawberry),new Fruit("樱桃",R.drawable.cherry),new Fruit("芒果",R.drawable.mango),};private List<Fruit> fruitList = new ArrayList<>();private FruitAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//获得Toolbar实例Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);setSupportActionBar(toolbar);//获得DrawerLayout实例mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);//获取NavigationView实例NavigationView navView = (NavigationView)findViewById(R.id.nav_view);//获得ActionBar实例ActionBar actionBar = getSupportActionBar();if (actionBar != null ){actionBar.setDisplayHomeAsUpEnabled(true);//显示导航按钮actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);//设置导航按钮图标}navView.setCheckedItem(R.id.nav_call);navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {@Overridepublic boolean onNavigationItemSelected(@NonNull MenuItem item) {mDrawerLayout.closeDrawers();return true;}});//获取FloatingActionButton实例FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab);fab.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//调用Snackbar的make()方法来创建一个Snackbar对象//make()方法第一个参数为当前界面布局的任意一个View;//第二个参数为Snackbar中显示的内容;//第三个参数为Snackbar显示的时长。Snackbar.make(view,"删除数据",Snackbar.LENGTH_SHORT)//调用setAction()方法设置动作,使之可以和用户进行交互.setAction("复原",new View.OnClickListener(){@Overridepublic void onClick(View view) {Toast.makeText(MainActivity.this,"数据恢复啦",Toast.LENGTH_SHORT).show();}}).show();}});initFruits();RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);//RecyclerView 内置的布局排列方式,网格布局排列方式,参数一:Context;参数二:列数GridLayoutManager layoutManager = new GridLayoutManager(MainActivity.this,2);recyclerView.setLayoutManager(layoutManager);adapter = new FruitAdapter(fruitList);recyclerView.setAdapter(adapter);}//进行水果的初始化,随机挑选五十个水果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;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()){case android.R.id.home:mDrawerLayout.openDrawer(GravityCompat.START);break;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;default:}return true;}}

Glide项目地址:/bumptech/glide

使用Glide加载水果图片 Glide在内部有许多复杂的逻辑结构,包括图片压缩,防止内存溢出。

Glide 用法:

首先调用Glide的with()方法,传入一个Context/Activity/Fragment参数

然后调用load()方法加载图片,传入一个URL地址或者本地路径或一个资源id

最后调用into()方法设置到具体某一个ImageView即可

整理学习自郭霖大佬的《第一行代码》

目前小白一名,持续学习Android中,如有错误请批评指正!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。