赞
踩
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/cardview_dark_background"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
background
设置颜色theme
设置主题色在这里的用法是仅改变Toolbar的主题为深色但是不影响,文字的颜色。
//设置导航栏
setSupportActionBar(toolbar);
//得到这个导航栏
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true); //打开homeAsUp按钮
actionBar.setHomeAsUpIndicator(R.drawable.apple); //为这个按钮设置图片
}
setDisplayHomeAsUpEnabled(true)
启用了返回箭头按钮。在onOptionsItemSelected
方法中,我们处理了箭头按钮的点击事件,通常使用onBackPressed()
方法来执行返回操作。
popupTheme
设置菜单颜色当我们使用theme设置主题颜色以后也会导致Toolbar上的菜单颜色发生变化,这时为了不影响菜单颜色我们又重新设置菜单颜色为浅色。
app命名是为了兼容低版本
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/apple" android:icon="@drawable/apple" android:title="apple" app:showAsAction="always"/> <item android:id="@+id/onion" android:icon="@drawable/onion" android:title="onion" app:showAsAction="ifRoom"/> <item android:id="@+id/tomato" android:icon="@drawable/tomato" android:title="tomato" app:showAsAction="never"/> </menu>
showAsAction指定按钮的显示位置,常用参数的意义
always
:总是显示在Toolbar中ifRoom
:如果有空间就显示在Toolbar,没有空间就显示在菜单中never
:永远显示在菜单中在MainActivity中使用**setSupportActionBar()**设置导航栏。
<?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/drawerlayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- 主内容视图 --> <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="@color/cardview_dark_background" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </FrameLayout> <com.google.android.material.navigation.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:menu="@menu/toolbar" /> <!-- 替换为您的菜单资源文件 --> </androidx.drawerlayout.widget.DrawerLayout>
通过按钮打开这个DrawerLayout
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); mDrawerlayout = (DrawerLayout) findViewById(R.id.drawerlayout); ActionBar actionBar = getSupportActionBar(); if(actionBar != null){ actionBar.setDisplayHomeAsUpEnabled(true); //打开homeAsUp按钮 actionBar.setHomeAsUpIndicator(R.drawable.apple); //为这个按钮设置图片 } } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { if(item.getItemId() == android.R.id.home){ mDrawerlayout.openDrawer(GravityCompat.START); //点击按钮后打开这个滑动窗口 } return true; } }
android.R.id.home:是HomeAsUp按钮的默认id
GravityCompat.START:用于启动滑动窗口的标识符
地址:https://github.com/hdodenhof/CircleImageView.git
dependencies {
...
implementation 'de.hdodenhof:circleimageview:3.1.0'
}
接下来编写一个新的显示界面nav_herder.xml
<?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="match_parent" android:padding="10dp"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/iconimg" android:layout_width="70dp" android:layout_height="70dp" android:src="@drawable/img" android:layout_centerInParent="true"/> <TextView android:id="@+id/mailtext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="204dp" android:text="s1793026645@126.com" android:textSize="15sp" /> <TextView android:id="@+id/userText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/iconimg" android:layout_marginTop="135dp" android:gravity="end" android:text="lukecc0" android:textSize="15sp" /> </RelativeLayout>
在activity_main
中将这个页面和刚才的menu
菜单一起加载到NavigationView
中显示。
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/toolbar"
app:headerLayout="@layout/nav_header"/>
打开滑动窗口后显示效果如下:
注意我们发现apple这个菜单选项是被选中的状态,是因为我们在MainActivity中使用这句代码设置的。nacview
NavigationView nacview = (NavigationView) findViewById(R.id.navigation_view);
nacview.setCheckedItem(R.id.apple); //设置为选中状态
nacview.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.tomato){
Toast.makeText(MainActivity.this, "666", Toast.LENGTH_SHORT).show();
}
if (item.getItemId() == R.id.apple){
//关闭滑动窗口
mDrawerlayout.close();
}
return true;
}
});
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="30dp"
android:src="@drawable/apple"
android:elevation="8dp"/>
这里使用app:elevation
属性来给FloatingActionButton指定一个高度值,高度值越大,投影范围也越大,但是投影效果越淡,高度值越小,投影范围也越小,但是投影效果越浓。
floatingActionButton = (FloatingActionButton) findViewById(R.id.FloatingButton);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "这是一条通知", Snackbar.LENGTH_SHORT)
.setAction("Undo", new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "你好", Toast.LENGTH_SHORT).show();
}
}).show();
}
});
在这里我们调用了Snackbar的make方法创建一个Snackbar对象,第一个参数是View,只要是任意一个View都可以他可以自己寻找到最外层布局。
然后使用setAction
可以为提示设置点击事件实现交互的目的。
相当于一个增强版的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="@color/cardview_dark_background" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/FloatingButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="30dp" android:src="@drawable/apple" android:elevation="8dp"/> </androidx.coordinatorlayout.widget.CoordinatorLayout>
可以看出它自动使得FloatingActionButton向上偏移了。
实际上MaterialCardView也属于FrameLayout,只是额外提供了阴影和圆角等效果。
制作一个RecyclerView的子布局fruit_item.xml,使用MaterialCardView
这个布局方式。
<?xml version="1.0" encoding="utf-8"?> <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto" 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/FruitImage" android:layout_width="match_parent" android:layout_height="100dp" android:scaleType="centerCrop"/> <TextView android:id="@+id/FruitText" 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>
接下来使用RecyclerView需要制作一个adapter
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; } } public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> { private Context mcontext; private List<Fruit> mfruit; public FruitAdapter(List<Fruit> mfruit) { this.mfruit = mfruit; } class ViewHolder extends RecyclerView.ViewHolder { FruitItemBinding binding; public ViewHolder(@NonNull View itemView) { super(itemView); binding = FruitItemBinding.bind(itemView); } } @NonNull @Override public FruitAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { //获取主视图的上下文 if (mcontext == null){ mcontext = parent.getContext(); } View view = LayoutInflater.from(mcontext).inflate(R.layout.fruit_item, parent, false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(@NonNull FruitAdapter.ViewHolder holder, int position) { Fruit fruit = mfruit.get(position); holder.binding.FruitText.setText(fruit.getName()); Glide.with(mcontext).load(fruit.getImageId()).into(holder.binding.FruitImage); } @Override public int getItemCount() { return mfruit.size(); } }
并且在activity_main布局中设置recyclerView
控件
最后在MainActivity中启动即可
initFruits();
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
GridLayoutManager gridLayoutManager = new GridLayoutManager(this,2);
recyclerView.setLayoutManager(gridLayoutManager);
FruitAdapter adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
GridLayoutManager
有两个参数,第二个参数意义是列数。
注意使用这种MaterialCardView
需要保证应用主题必须是 Theme.MaterialComponents
或其后代主题。
显示效果如下:
在这里发现我们的Toolbar
不见了,仔细观察发现被recyclerView
遮挡了。这时候就需要另外一个工具——AppBarLayout
用于和recyclerView进行交互作用,
<com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/cardview_dark_background" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_scrollFlags="scroll|enterAlways|snap"/></com.google.android.material.appbar.AppBarLayout> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
首先我们定义了一个AppBarLayout将Toolbar放入AppBarLayout中。然后在RecyclerView中使用app:layout_behavior
属性指定了一个布局行为,
appbar_scrolling_view_behavior
这个字符串也是Material
库提供的。
通过app:layout_behavior
这个属性可以解决遮挡问题。可以看出它将recyclerView向下挤压了。
app:layout_behavior="@string/appbar_scrolling_view_behavior"
是用于指定一个视图在滚动时与AppBarLayout
一起协调工作的属性。这个属性通常用于将滚动行为与CoordinatorLayout
和AppBarLayout
一起使用,以实现复杂的滚动效果
还记得我们在父布局使用的CoordinatorLayout
吗?他可以用于监听控件变化。
可以使用 app:layout_scrollFlags
属性来定义 AppBarLayout
的滚动行为。
下面是一些常见的 layout_scrollFlags
标志:
scroll
: 指示该视图可以在滚动时折叠,即它会随着滚动事件的发生而逐渐变小。enterAlways
: 指示该视图在向下滚动时,会立即进入可见状态。通常与 scroll
一起使用。snap
: 指示该视图会在滚动结束时对齐到最近的折叠状态,以产生“捕捉”效果。首先导入依赖:
依赖地址: 谷歌API参考文档
dependencies {
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
}
我们接下来使用SwipRefreshLayout将RecyclerView包住
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swiprefresh"
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/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
然后我们还需设置具体的刷新逻辑才可以实现刷新功能。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); swipeRefreshLayout = (SwipeRefreshLayout) findViewById((int) R.id.swiprefresh); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { //调用写好的刷新逻辑 refreshFruits(); } }); } //具体刷新逻辑 private void refreshFruits(){ new Thread(new Runnable() { @Override public void run() { try { //因为本地刷新很快,这样便于我们观察到刷新效果 Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } runOnUiThread(new Runnable() { @Override public void run() { initFruits(); //通知RecyclerView刷新 adapter.notifyDataSetChanged(); //表示刷新事件结束,隐藏进度条 swipeRefreshLayout.setRefreshing(false); } }); } }).start(); }
最终显示效果如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。