当前位置: 移动技术网 > 移动技术>移动开发>Android > Android开发使用MateriDesign(一套全新的界面设计语言)

Android开发使用MateriDesign(一套全新的界面设计语言)

2020年08月05日  | 移动技术网移动技术  | 我要评论

什么是MaterialDesig

MaterialDesign是由Google基于传统的设计原则,设计出的一套全新的界面设计语言,包含了视觉、运动、互动效果等特性。

Toolbar

Toolbar由AndroidX库提供。

可以使用Theme.AppCompat.NoActionBar和Theme.AppCompat.Light.NoActionBar两种主题。

使用Theme.AppCompat.Light.NoActionBar主题示例:

<resources> <!-- Base application theme. --> <!--将parent取值改为Theme.AppCompat.Light.NoActionBar--> <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> </resources> 

新建Toolbar来代替ActionBar,布局文件示例代码:

<?xml version="1.0" encoding="utf-8"?> <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"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> </FrameLayout> 

在Activity中关联:

public class MainActivity extends AppCompatActivity { private Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //关联Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); } } 

如果要修改Toolbar标题栏显示的标题,可以在与之关联的Activity上做修改:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zcd.flcmaterialdesigndemo"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/TestTitle"><!--新的标题内容--> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 

即,在Manifest文件中对应的Activity上添加/修改android:label属性的取值。

新建一个菜单文件:

<?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/toolbar_backup" android:icon="@mipmap/back_up" android:title="@string/ToolbarBackup" app:showAsAction="always"/> <item android:id="@+id/toolbar_delete" android:icon="@mipmap/delete" android:title="@string/ToolbarDelete" app:showAsAction="ifRoom"/> <item android:id="@+id/toolbar_settings" android:icon="@mipmap/settings" android:title="@string/ToolbarSettings" app:showAsAction="never"/> </menu> 

app:showAsAction用于指定按钮显示的位置。

app:showAsAction的常见取值:

  • always

    表示永远显示在Toolbar中,如果屏幕空间不够则不显示;

  • ifRoom

    表示屏幕空间足够的情况下才显示在Toolbar中,不够就显示在菜单中;

  • never

    表示永远显示在菜单中;

Toolbar中的action按钮只会显示图标,菜单中的action按钮指挥显示文字。

关联点击事件:

public class MainActivity extends AppCompatActivity { private Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //关联Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); } @Override 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.toolbar_backup: Toast.makeText(this, "点击了返回", Toast.LENGTH_LONG).show(); break; case R.id.toolbar_delete: Toast.makeText(this, "点击了删除", Toast.LENGTH_LONG).show(); break; case R.id.toolbar_settings: Toast.makeText(this, "点击了设置", Toast.LENGTH_LONG).show(); break; } return true; } } 

滑动菜单

滑动菜单时MaterialDesign中最常见的效果之一。

DrawerLayout

所谓滑动菜单,就是将一些菜单的选项隐藏起来,而不是将其直接放在主屏幕上,然后通过滑动的方式将菜单显示出来。

创建滑动菜单布局文件:

<?xml version="1.0" encoding="utf-8"?> <androidx.drawerlayout.widget.DrawerLayout xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" 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"> <androidx.appcompat.widget.Toolbar android:id="@+id/drawer_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> </FrameLayout> <!--滑动菜单要显示的内容左侧--> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:background="#FFF" android:text="@string/DrawerLayoutTVLeft" android:textSize="30sp"/> <!--滑动菜单要显示的内容右侧--> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="end" android:background="#FFF" android:text="@string/DrawerLayoutTVRight" android:textSize="30sp"/> </androidx.drawerlayout.widget.DrawerLayout> 

子控件的android:layout_gravity属性用来设置是左侧划出还是右侧划出,但是在一个DrawerLayout中不能有两个划出方式相同的子控件。

如果觉得通过滑动屏幕边缘不方便或者与屏幕手势冲突的话可以使用按钮将滑动菜单弹出:

public class DrawerActivity extends AppCompatActivity { private Toolbar toolbar; private DrawerLayout drawerLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.drawer_activity); //关联Toolbar toolbar = findViewById(R.id.drawer_toolbar); setSupportActionBar(toolbar); //添加弹出滑动菜单的功能 drawerLayout = findViewById(R.id.drawer_layout); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeAsUpIndicator(R.mipmap.get_right); } @Override 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.toolbar_backup: Toast.makeText(this, "点击了返回", Toast.LENGTH_LONG).show(); break; case R.id.toolbar_delete: Toast.makeText(this, "点击了删除", Toast.LENGTH_LONG).show(); break; case R.id.toolbar_settings: Toast.makeText(this, "点击了设置", Toast.LENGTH_LONG).show(); break; //添加弹出滑动菜单的响应 case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); } return true; } } 

通过getSupportActionBar()方法来获取ActionBar的实例,通过调用setDisplayHomeAsUpEnabled()方法来显示按钮,并通过setHomeAsUpIndicator()方法来指定按钮的图标。

添加的这个按钮有个专门的名字,叫做Home按钮,它有专门的id为android.R.id.home。

在菜单点击事件监听中,可以通过调用DrawerLayout.openDrawer()方法来将滑动菜单弹出。

DrawerLayout.openDrawer()方法的取值对应布局文件中控件android:layout_gravity属性的取值。

Navigation View

通过NavigationVIew来对滑动菜单定制任意布局。

引入依赖:

implementation 'com.google.android.material:material:1.0.0'
implementation 'de.hdodenhof:circleimageview:3.0.1' 

使用NavigationView之前需要准备一个menu和一个headerlayout,menu用于显示NavigationView中的菜单,headerlayout用来显示NavigationVIew的头部。

建立一个单选菜单:

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_friends" android:title="@string/NavItemFriends" android:icon="@mipmap/friends"/> <item android:id="@+id/nav_disk" android:title="@string/NavDisk" android:icon="@mipmap/disk"/> <item android:id="@+id/nav_mail" android:title="@string/NavItemMail" android:icon="@mipmap/mail"/> <item android:id="@+id/nav_task" android:title="@string/NavItmeTask" android:icon="@mipmap/task"/> </group> </menu> 

实现一个单选菜单的方式是,指定group的行为模式,然后在group中添加一组item作为子控件。

创建一个头部文件:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="180dp" android:padding="10dp" android:background="@color/colorPrimary"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/nav_header" android:layout_width="70dp" android:layout_height="70dp" android:src="@mipmap/me" android:layout_centerInParent="true"/> <TextView android:id="@+id/nav_header_username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/NavHeaderDefaultUsername" android:textColor="#FFF" android:textSize="14sp" android:layout_above="@+id/nav_header_email"/> <TextView android:id="@+id/nav_header_email" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/NavHeaderDefaultMail" android:textColor="#FFF" android:textSize="14sp" android:layout_alignParentBottom="true"/> </RelativeLayout> 

创建一个布局使用NavigationView:

<?xml version="1.0" encoding="utf-8"?> <androidx.drawerlayout.widget.DrawerLayout xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/nav_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/nav_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> </FrameLayout> <!--引入头部以及菜单--> <com.google.android.material.navigation.NavigationView android:id="@+id/nav_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" app:menu="@menu/nav_menu" app:headerLayout="@layout/nav_header"> </com.google.android.material.navigation.NavigationView> </androidx.drawerlayout.widget.DrawerLayout> 

为菜单项添加点击事件:

public class NavViewActivity extends AppCompatActivity { private Toolbar toolbar; private DrawerLayout drawerLayout; private NavigationView navView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.nav_layout); //关联Toolbar toolbar = findViewById(R.id.nav_toolbar); setSupportActionBar(toolbar); //添加弹出滑动菜单的功能 drawerLayout = findViewById(R.id.nav_layout); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeAsUpIndicator(R.mipmap.get_right); //绑定NavigationView并为菜单项添加点击事件 navView = findViewById(R.id.nav_view); //默认选中项 navView.setCheckedItem(R.id.nav_friends); navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { //点击菜单项,关闭滑动菜单 drawerLayout.closeDrawers(); //返回true表示已经被处理 return true; } }); } @Override 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.toolbar_backup: Toast.makeText(this, "点击了返回", Toast.LENGTH_LONG).show(); break; case R.id.toolbar_delete: Toast.makeText(this, "点击了删除", Toast.LENGTH_LONG).show(); break; case R.id.toolbar_settings: Toast.makeText(this, "点击了设置", Toast.LENGTH_LONG).show(); break; //添加弹出滑动菜单的响应 case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); } return true; } } 

悬浮按钮和可交互提示

按照MaterialDesign的设计理念,应用的界面不仅仅是一个平面。

比如,悬浮按钮,它并不属于主界面的一部分。

FloatingActionButton

该控件用于实现悬浮按钮的效果。

示例代码:

<!--添加的悬浮按钮--> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/nav_btn_floating" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@mipmap/done" android:elevation="8dp"/> 

android:elevation属性为悬浮按钮的悬浮高度,高度越高,投影范围越大,投影效果越淡。

添加点击事件:

//为悬浮按钮添加点击事件 fab = findViewById(R.id.nav_btn_floating); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(NavViewActivity.this, "点击了悬浮按钮", Toast.LENGTH_LONG).show(); } }); 

Snackbar

Snackbar并不是Toast的替代品。

Toast的作用是gap苏用户现在发生了什么,但用户只能被动的接收这个事情。

与Toast相比,Snack扩展了交互功能,即在告诉用户的同时,还可以让用户进行一定的操作。

示例代码:

//使用Snackbar Snackbar.make(v, "提示信息", Snackbar.LENGTH_LONG) .setAction("不做处理", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(NavViewActivity.this, "点击了不做处理选项", Toast.LENGTH_LONG).show(); } }) .show(); 

CoordinatorLayout

如果在FrameLayout中使用Snackbar并且此时还有一个悬浮按钮,在弹出消息的同时如果悬浮按钮正好位于底部,弹出的消息会将按钮遮挡。

使用CoordinatorLayout替换之后的布局文件:

<androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/nav_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> <!--添加的悬浮按钮--> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/nav_btn_floating" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@mipmap/done" android:elevation="8dp"/> </androidx.coordinatorlayout.widget.CoordinatorLayout> 

FrameLayout替换成androidx.coordinatorlayout.widget.CoordinatorLayout即可。

卡片式布局

卡片式布局可以让页面中的元素看起来就像是在卡片中一样,并且还能有圆角和投影。

MaterialCardView

引入依赖:

implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.github.bumptech.glide:glide:4.9.0' 

建立一个与图片相关的实体类Picture:

public class Picture { private String name; private Integer imgId; public Picture() { } public Picture(String name, Integer imgId) { this.name = name; this.imgId = imgId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getImgId() { return imgId; } public void setImgId(Integer imgId) { this.imgId = imgId; } @Override public String toString() { return "Picture{" + "name='" + name + '\'' + ", imgId=" + imgId + '}'; } } 

创建MaterialCardView:

<?xml version="1.0" encoding="utf-8"?> <com.google.android.material.card.MaterialCardView 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:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/mcv_picture" android:layout_width="match_parent" android:layout_height="100dp" android:scaleType="centerCrop"/> <TextView android:id="@+id/mcv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_margin="5dp" android:textSize="16sp"/> </LinearLayout> </com.google.android.material.card.MaterialCardView> 

创建一个PictureAdapter适配器:

public class PictureAdapter extends RecyclerView.Adapter<PictureAdapter.PictureViewHolder> { private Context mContext = null; private List<Picture> pictures = new ArrayList<>(); public PictureAdapter(Context mContext) { this.mContext = mContext; initPictures(); } private void initPictures() { for (int i = 1; i <= 9; i++) { Picture picture = new Picture(); picture.setName("图片" + i); if (i%2 == 1){ picture.setImgId(R.mipmap.settings); }else { picture.setImgId(R.mipmap.task); } pictures.add(picture); } } @NonNull @Override public PictureViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.picture_item_layout, parent, false); return new PictureViewHolder(view); } @Override public void onBindViewHolder(@NonNull PictureViewHolder holder, int position) { Picture cursor = pictures.get(position); holder.pictureName.setText(cursor.getName()); Glide.with(mContext).load(cursor.getImgId()).into(holder.pictureView); } @Override public int getItemCount() { return pictures.size(); } public class PictureViewHolder extends RecyclerView.ViewHolder{ public TextView pictureName = null; public ImageView pictureView = null; public PictureViewHolder(@NonNull View itemView) { super(itemView); pictureName = itemView.findViewById(R.id.mcv_name); pictureView = itemView.findViewById(R.id.mcv_picture); } } } 

使用Glide加载图片时,不用担心高像素的图片加载时内存溢出的问题,Glide会自动压缩图片。

在Activity中加载:

//加载MaterialCardView recyclerView = findViewById(R.id.my_recycler_view); GridLayoutManager manager = new GridLayoutManager(this, 2); recyclerView.setLayoutManager(manager); PictureAdapter adapter = new PictureAdapter(this); recyclerView.setAdapter(adapter); 

但是此时的RecyclerView会将ToolBar遮盖。

AppBarLayout

将ToolBar嵌套在AppBarLayout中:

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

并指定RecyclerView的行为,使其可以滑动:

<androidx.recyclerview.widget.RecyclerView android:id="@+id/my_recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> 

给Toolbar添加滑动动作app:layout_scrollFlags

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

app:layout_scrollFlags属性常见取值:

  • scroll

    scroll表示RecyclerView向上滚动时,Toolbar也会随着向上滚动并最终隐藏;

  • enterAlways

    enterAlways表示RecyclerView向下滚动时,Toolbar也会随着向下滚动并最终显示完全;

  • snap

    snap表示当Toolbar没有完全隐藏或者显示的时候,会根据当前滚动的距离自动选择是隐藏还是显示;

  • enterAlwaysCollapsed

    这里涉及到Child View的高度和最小高度,向下滚动时,Child View先向下滚动最小高度值,然后Scrolling View开始滚动,到达边界时,Child View再向下滚动,直至显示完全;

  • exitUntilCollapsed

    发生向上滚动事件时,Child View向上滚动退出直至最小高度,然后Scrolling View开始滚动。也就是,Child View不会完全退出屏幕;

下拉刷新

SwipeRefreshLayout就是用于实现下拉刷新功能的核心类,它由AndroidX库提供。

在布局文件中,使用SwipeRefreshLayout将要刷新的控件嵌套在内部:

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

在适配器中添加更新图片用的方法:

public void initNewPictures(){ pictures.clear(); for (int i = 1; i <= 19; i++) { Picture picture = new Picture(); picture.setName("图片" + i); if (i%2 == 1){ picture.setImgId(R.mipmap.me); }else { picture.setImgId(R.mipmap.mail); } pictures.add(picture); } } 

在Activity中设置事件监听并更新UI:

public class NavViewActivity extends AppCompatActivity { private Toolbar toolbar; private DrawerLayout drawerLayout; private NavigationView navView; private FloatingActionButton fab; private RecyclerView recyclerView = null; private SwipeRefreshLayout swipeRefreshLayout = null; private PictureAdapter adapter = null; private int updateUICode = 200; private Handler mHandler = new Handler(){ @Override public void handleMessage(@NonNull Message msg) { if (msg.what == updateUICode){ adapter.initNewPictures(); adapter.notifyDataSetChanged(); swipeRefreshLayout.setRefreshing(false); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.nav_layout); //关联Toolbar toolbar = findViewById(R.id.nav_toolbar); setSupportActionBar(toolbar); //添加弹出滑动菜单的功能 drawerLayout = findViewById(R.id.nav_layout); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeAsUpIndicator(R.mipmap.get_right); //绑定NavigationView并为菜单项添加点击事件 navView = findViewById(R.id.nav_view); //默认选中项 navView.setCheckedItem(R.id.nav_friends); navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { //点击菜单项,关闭滑动菜单 drawerLayout.closeDrawers(); //返回true表示已经被处理 return true; } }); //为悬浮按钮添加点击事件 fab = findViewById(R.id.nav_btn_floating); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Toast.makeText(NavViewActivity.this, "点击了悬浮按钮", Toast.LENGTH_LONG).show(); //使用Snackbar Snackbar.make(v, "提示信息", Snackbar.LENGTH_LONG) .setAction("不做处理", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(NavViewActivity.this, "点击了不做处理选项", Toast.LENGTH_LONG).show(); } }) .show(); } }); //加载MaterialCardView recyclerView = findViewById(R.id.my_recycler_view); GridLayoutManager manager = new GridLayoutManager(this, 2); recyclerView.setLayoutManager(manager); adapter = new PictureAdapter(this); recyclerView.setAdapter(adapter); //下拉刷新事件监听 swipeRefreshLayout = findViewById(R.id.my_recycler_srl); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { initNewData(); } }); } /**
     * 模拟获取新数据
     */ private void initNewData(){ new Thread(new Runnable() { @Override public void run() { try { //模拟耗时操作 Thread.sleep(2000); Message msg = new Message(); msg.what = updateUICode; mHandler.sendMessage(msg); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } @Override 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.toolbar_backup: Toast.makeText(this, "点击了返回", Toast.LENGTH_LONG).show(); break; case R.id.toolbar_delete: Toast.makeText(this, "点击了删除", Toast.LENGTH_LONG).show(); break; case R.id.toolbar_settings: Toast.makeText(this, "点击了设置", Toast.LENGTH_LONG).show(); break; //添加弹出滑动菜单的响应 case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); } return true; } } 

可折叠式标题栏

CollapsingToolbarLayout

CollapsingToolbarLayout并不能单独存在,仅仅可以作为AppBarLayout的子控件存在。

AppBarLayout又必须是CoordinatorLayout的子控件。

app:layout_collapseMode属性的取值:

  • parallax

    在折叠过程中位置固定;

  • pin

    在折叠过程中位置会发生错位;

NestedScrollView与SrcollView相比增加了对滚动事件的监听。

app:layout_anchor属性意为锚点,锚点的取值为该控件显示的区域。

app:layout_anchorGravity属性意为锚点的定位。

布局文件:

<?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/ct_appbar" android:layout_width="match_parent" android:layout_height="250dp"> <com.google.android.material.appbar.CollapsingToolbarLayout android:id="@+id/ct_collapsing" android:layout_width="match_parent" android:layout_height="match_parent" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:contentScrim="@color/colorPrimary" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:id="@+id/ct_appbar_image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" app:layout_collapseMode="parallax"/> <androidx.appcompat.widget.Toolbar android:id="@+id/ct_appbar_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> <!--显示内容--> <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"> <com.google.android.material.card.MaterialCardView 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:id="@+id/ct_picture_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp"/> </com.google.android.material.card.MaterialCardView> </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/done" app:layout_anchor="@id/ct_appbar" app:layout_anchorGravity="bottom|end"/> </androidx.coordinatorlayout.widget.CoordinatorLayout> 

在适配其中添加点击跳转:

public class PictureAdapter extends RecyclerView.Adapter<PictureAdapter.PictureViewHolder> { private Context mContext = null; private List<Picture> pictures = new ArrayList<>(); public PictureAdapter(Context mContext) { this.mContext = mContext; initPictures(); } private void initPictures() { for (int i = 1; i <= 19; i++) { Picture picture = new Picture(); picture.setName("图片" + i); if (i%2 == 1){ picture.setImgId(R.mipmap.settings); }else { picture.setImgId(R.mipmap.task); } pictures.add(picture); } } public void initNewPictures(){ pictures.clear(); for (int i = 1; i <= 19; i++) { Picture picture = new Picture(); picture.setName("图片" + i); if (i%2 == 1){ picture.setImgId(R.mipmap.me); }else { picture.setImgId(R.mipmap.mail); } pictures.add(picture); } } @NonNull @Override public PictureViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.picture_item_layout, parent, false); final PictureViewHolder holder = new PictureViewHolder(view); //点击事件 holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = holder.getAdapterPosition(); Picture cursor = pictures.get(position); Intent intent = new Intent(mContext, CollapsingActivity.class); intent.putExtra("name", cursor.getName()); intent.putExtra("id", cursor.getImgId()); mContext.startActivity(intent); } }); return holder; } @Override public void onBindViewHolder(@NonNull PictureViewHolder holder, int position) { Picture cursor = pictures.get(position); holder.pictureName.setText(cursor.getName()); Glide.with(mContext).load(cursor.getImgId())

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网