Android仿优酷圆形菜单学习笔记分享
作者:TheMrNice 发布时间:2023-07-31 06:02:31
本文实例为大家分享了Android优酷圆形菜单的具体代码,供大家参考,具体内容如下
先来看看效果:
首先来分析一下:
这个菜单可以分成三个菜单:
1.一级菜单(即最内圈那个菜单)
2.二级菜单(即中间圈那个菜单)
3. * 菜单(即最外圈那个菜单)
首先,可以将这三个菜单使用相对布局
一级菜单只有一个按钮(即home),可以控制二级和 * 菜单
二级菜单有三个按钮(即menu),中间那个按钮可以控制 * 菜单
* 菜单有七个按钮
那先把布局文件先写出来,采用三个相对布局(即每个菜单采用一个相对布局)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.youkumenu.MainActivity" >
<!-- * 菜单 -->
<RelativeLayout
android:id="@+id/level3_Rl"
android:layout_width="220dp"
android:layout_height="110dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3" >
<ImageView
android:id="@+id/channel1"
android:layout_marginLeft="5dp"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel1"/>
<ImageView
android:id="@+id/channel2"
android:layout_marginBottom="10dp"
android:layout_marginLeft="25dp"
android:layout_above="@id/channel1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel2"/>
<ImageView
android:layout_marginBottom="1dp"
android:layout_marginLeft="52dp"
android:layout_above="@id/channel2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel3"/>
<ImageView
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel4"/>
<ImageView
android:id="@+id/channel7"
android:layout_marginRight="5dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel7"/>
<ImageView
android:id="@+id/channel6"
android:layout_alignParentRight="true"
android:layout_marginBottom="10dp"
android:layout_marginRight="25dp"
android:layout_above="@id/channel7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel6"/>
<ImageView
android:layout_marginBottom="1dp"
android:layout_marginRight="52dp"
android:layout_alignParentRight="true"
android:layout_above="@id/channel6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel5"/>
</RelativeLayout>
<!-- 二级菜单 -->
<RelativeLayout
android:id="@+id/level2_Rl"
android:layout_width="140dp"
android:layout_height="70dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" >
<ImageView
android:layout_marginLeft="3dp"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_search"/>
<ImageView
android:id="@+id/menu_Iv"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_menu"/>
<ImageView
android:id="@+id/myyouku_Iv"
android:layout_marginRight="3dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_myyouku"/>
</RelativeLayout>
<!-- 一级菜单 -->
<RelativeLayout
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1" >
<ImageView
android:id="@+id/home_Iv"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_home" />
</RelativeLayout>
</RelativeLayout>
那好,布局写好,就能看到这样的效果,只不过现在只是静态的,没有加逻辑而已
下面就该来分析下逻辑了,先来看看home(即一级菜单中间那个按钮)
点击home,会有三种情况,下面分情况考虑:
情况1.二级、 * 菜单都显示,就将二、 * 菜单隐藏掉
情况2.二、 * 菜单都不显示的时候,就将二级菜单显示
情况3.二级菜单显示且 * 菜单不显示的时候,就将二级菜单隐藏
当然我们知道,要知道菜单隐藏或者显示,只需要设个标记位即可
那要如何隐藏或显示菜单,当然是使用动画了,可以使用补间动画和
属性动画,我这里就使用补间动画
下面就该来分析下逻辑了,先来看看menu(即二级菜单中间那个按钮)
点击menu,会有三种情况,下面分情况考虑:
情况1. * 显示的时候,就将 * 菜单隐藏
情况2. * 隐藏的时候,就将 * 菜单显示
这个就比较简单了,就两种情况。
public class MainActivity extends Activity implements OnClickListener{
//一级菜单中的home按钮
private ImageView home_Iv;
//二级菜单中的Menu按钮
private ImageView menu_Iv;
//用于判断二级菜单的显示状况,true为显示,false为隐藏
private boolean level2ListPlay = true;
//用于判断二级菜单的显示状况,true为显示,false为隐藏
private boolean level3ListPlay = true;
//二级和 * 菜单
private RelativeLayout level2_Rl,level3_Rl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
//初始化组件
private void initView() {
home_Iv = (ImageView) findViewById(R.id.home_Iv);
home_Iv.setOnClickListener(this);
level2_Rl = (RelativeLayout) findViewById(R.id.level2_Rl);
level3_Rl = (RelativeLayout) findViewById(R.id.level3_Rl);
menu_Iv = (ImageView) findViewById(R.id.menu_Iv);
menu_Iv.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.home_Iv: //点击home按钮的逻辑代码
clickHomeIv();
break;
case R.id.menu_Iv:
clickMenuIv(); //点击二级菜单中的menu按钮的逻辑代码
break;
default:
break;
}
}
//点击二级菜单中的menu按钮的逻辑代码
private void clickMenuIv() {
//分情况考虑
//1. * 显示的时候,就将 * 菜单隐藏
if (level3ListPlay) {
hideMenu(level3_Rl,0);
level3ListPlay = false;
return;
}
//2. * 隐藏的时候,就将 * 菜单显示
if (!level3ListPlay) {
showMenu(level3_Rl);
level3ListPlay = true;
return;
}
}
//点击一级菜单中的home按钮的逻辑代码
private void clickHomeIv() {
//分情况考虑
//1.二级、 * 菜单都显示,就将二、 * 菜单隐藏掉
if (level2ListPlay && level3ListPlay) {
//将二 * 菜单隐藏,并改变标记
hideMenu(level2_Rl,300);
hideMenu(level3_Rl,500);
level2ListPlay = false;
level3ListPlay = false;
return;
}
//2.二、 * 菜单都不显示的时候,就将二级菜单显示
if (!level2ListPlay && !level3ListPlay) {
showMenu(level2_Rl);
level2ListPlay = true;
return;
}
//3.二级菜单显示且 * 菜单不显示的时候,就将二级菜单隐藏
if (level2ListPlay && !level3ListPlay) {
hideMenu(level2_Rl,0);
level2ListPlay = false;
return;
}
}
/**
* 显示菜单
* @param view 要显示的菜单
*/
private void showMenu(RelativeLayout view) {
// view.setVisibility(View.VISIBLE);
//旋转动画
RotateAnimation animation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 1.0f);
animation.setDuration(500); //设置动画持续的时间
animation.setFillAfter(true); //动画停留在动画结束的位置
view.startAnimation(animation);
}
/**
* 隐藏菜单
* @param view 要隐藏的菜单 ,startOffset 动画延迟执行的时间
*/
private void hideMenu(RelativeLayout view,long startOffset) {
// view.setVisibility(View.GONE);
/**
* 旋转动画
* RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue)
* fromDegrees 开始旋转角度
* toDegrees 旋转的结束角度
* pivotXType X轴 参照物 (X轴的伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF)
* pivotXValue x轴 旋转的参考点(x坐标的伸缩值)
* pivotYType Y轴 参照物 (Y轴的伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF)
* pivotYValue Y轴 旋转的参考点 ((Y坐标的伸缩值) )
*/
RotateAnimation animation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 1.0f);
animation.setDuration(500);
animation.setFillAfter(true); //动画停留在动画结束的位置
animation.setStartOffset(startOffset); //设置动画的延迟执行
view.startAnimation(animation);
}
}
写到这里,应该差不多可以看到效果了,但是细心的伙伴应该会发现两个bug:
第一:当你快速点击一级菜单home按钮或二级菜单menu按钮的时候,会发现二级菜单或 * 菜单的第一次动画还没执行完,又执行第二次动画,看起来就在晃一样。(原因:就是执行的动画都设定了一定时间,你点击的时间快于动画执行的时间)
解决办法:
对动画进行监听,当动画开始执行和结束的时候,对它进行监听,大家应该会想到用一个标记位来判断,可我们知道一个标记为只能判断两种状态,可这里有两种动画(显示的动画和隐藏的动画),一个标记位肯定不行,可以用一个Int值来控制
//用于记录有多少个动画在执行
private int annimationCount = 0;
//对动画进行监听的时候
animation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// menu_Iv.setOnClickListener(null);
// home_Iv.setOnClickListener(null);
annimationCount ++;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
// menu_Iv.setOnClickListener(MainActivity.this);
// home_Iv.setOnClickListener(MainActivity.this);
annimationCount --;
}
//当点击的时候就可以进行判断,只要annimationCount值大于0,说明还有动画在执行
if (annimationCount > 0) {
return ;
}
第二:当二级菜单隐藏的时候,你点击二级菜单中menu按钮(虽然现在看不见)时,你会惊奇的发现 * 菜单居然显示了。(原因:补间动画,没有真正的改变组件的属性,而属性动画就不一样,大家有时间可以试试属性动画做做)
解决办法:
只要当二级菜单隐藏的时候,就让二级菜单的所有选项按钮都不可点。因为二级菜单有可以能有多个按钮,所以拿到父容器,去使它的子控件失去焦点即可。
//如果要显示菜单,那么就将相应的控件设为有焦点
//获取父容器中有几个子控件
int childCount = view.getChildCount();
for (int i = 0; i < childCount; i++) {
view.getChildAt(i).setEnabled(true);
}
写到这里就差不多了,大家可以试试
这里把我写的完整代码贴出来:
public class MainActivity extends Activity implements OnClickListener{
//一级菜单中的home按钮
private ImageView home_Iv;
//二级菜单中的Menu按钮
private ImageView menu_Iv;
//用于判断二级菜单的显示状况,true为显示,false为隐藏
private boolean level2ListPlay = true;
//用于判断二级菜单的显示状况,true为显示,false为隐藏
private boolean level3ListPlay = true;
//二级和 * 菜单
private RelativeLayout level2_Rl,level3_Rl;
//用于记录有多少个动画在执行
private int annimationCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
//初始化组件
private void initView() {
home_Iv = (ImageView) findViewById(R.id.home_Iv);
home_Iv.setOnClickListener(this);
level2_Rl = (RelativeLayout) findViewById(R.id.level2_Rl);
level3_Rl = (RelativeLayout) findViewById(R.id.level3_Rl);
menu_Iv = (ImageView) findViewById(R.id.menu_Iv);
menu_Iv.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.home_Iv: //点击home按钮的逻辑代码
clickHomeIv();
break;
case R.id.menu_Iv:
clickMenuIv(); //点击二级菜单中的menu按钮的逻辑代码
break;
default:
break;
}
}
//点击二级菜单中的menu按钮的逻辑代码
private void clickMenuIv() {
//当点击的时候就可以进行判断,只要annimationCount值大于0,说明还有动画在执行
if (annimationCount > 0) {
return ;
}
//分情况考虑
//1. * 显示的时候,就将 * 菜单隐藏
if (level3ListPlay) {
hideMenu(level3_Rl,0);
level3ListPlay = false;
return;
}
//2. * 隐藏的时候,就将 * 菜单显示
if (!level3ListPlay) {
showMenu(level3_Rl);
level3ListPlay = true;
return;
}
}
//点击一级菜单中的home按钮的逻辑代码
private void clickHomeIv() {
//当点击的时候就可以进行判断,只要annimationCount值大于0,说明还有动画在执行
if (annimationCount > 0) {
return ;
}
//分情况考虑
//1.二级、 * 菜单都显示,就将二、 * 菜单隐藏掉
if (level2ListPlay && level3ListPlay) {
//将二 * 菜单隐藏,并改变标记
hideMenu(level2_Rl,300);
hideMenu(level3_Rl,500);
level2ListPlay = false;
level3ListPlay = false;
return;
}
//2.二、 * 菜单都不显示的时候,就将二级菜单显示
if (!level2ListPlay && !level3ListPlay) {
showMenu(level2_Rl);
level2ListPlay = true;
return;
}
//3.二级菜单显示且 * 菜单不显示的时候,就将二级菜单隐藏
if (level2ListPlay && !level3ListPlay) {
hideMenu(level2_Rl,0);
level2ListPlay = false;
return;
}
}
/**
* 显示菜单
* @param view 要显示的菜单
*/
private void showMenu(RelativeLayout view) {
// view.setVisibility(View.VISIBLE);
//如果要显示菜单,那么就将相应的控件设为有焦点
//获取父容器中有几个子控件
int childCount = view.getChildCount();
for (int i = 0; i < childCount; i++) {
view.getChildAt(i).setEnabled(true);
}
//旋转动画
RotateAnimation animation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 1.0f);
animation.setDuration(500); //设置动画持续的时间
animation.setFillAfter(true); //动画停留在动画结束的位置
view.startAnimation(animation);
animation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始的时候回调
// menu_Iv.setOnClickListener(null);
// home_Iv.setOnClickListener(null);
annimationCount ++;
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画执行过程调用
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束的时候调用
// menu_Iv.setOnClickListener(MainActivity.this);
// home_Iv.setOnClickListener(MainActivity.this);
annimationCount --;
}
});
}
/**
* 隐藏菜单
* @param view 要隐藏的菜单 ,startOffset 动画延迟执行的时间
*/
private void hideMenu(RelativeLayout view,long startOffset) {
// view.setVisibility(View.GONE);
//如果要隐藏菜单,那么就将相应的控件设为没有焦点
//获取父容器中有几个子控件
int childCount = view.getChildCount();
for (int i = 0; i < childCount; i++) {
view.getChildAt(i).setEnabled(false);
}
/**
* 旋转动画
* RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue)
* fromDegrees 开始旋转角度
* toDegrees 旋转的结束角度
* pivotXType X轴 参照物 (X轴的伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF)
* pivotXValue x轴 旋转的参考点(x坐标的伸缩值)
* pivotYType Y轴 参照物 (Y轴的伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF)
* pivotYValue Y轴 旋转的参考点 ((Y坐标的伸缩值) )
*/
RotateAnimation animation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 1.0f);
animation.setDuration(500);
animation.setFillAfter(true); //动画停留在动画结束的位置
animation.setStartOffset(startOffset); //设置动画的延迟执行
view.startAnimation(animation);
animation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// menu_Iv.setOnClickListener(null);
// home_Iv.setOnClickListener(null);
annimationCount ++;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
// menu_Iv.setOnClickListener(MainActivity.this);
// home_Iv.setOnClickListener(MainActivity.this);
annimationCount --;
}
});
}
}
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.youkumenu.MainActivity" >
<!-- * 菜单 -->
<RelativeLayout
android:id="@+id/level3_Rl"
android:layout_width="220dp"
android:layout_height="110dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3" >
<ImageView
android:id="@+id/channel1"
android:layout_marginLeft="5dp"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel1"/>
<ImageView
android:id="@+id/channel2"
android:layout_marginBottom="10dp"
android:layout_marginLeft="25dp"
android:layout_above="@id/channel1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel2"/>
<ImageView
android:layout_marginBottom="1dp"
android:layout_marginLeft="52dp"
android:layout_above="@id/channel2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel3"/>
<ImageView
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel4"/>
<ImageView
android:id="@+id/channel7"
android:layout_marginRight="5dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel7"/>
<ImageView
android:id="@+id/channel6"
android:layout_alignParentRight="true"
android:layout_marginBottom="10dp"
android:layout_marginRight="25dp"
android:layout_above="@id/channel7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel6"/>
<ImageView
android:layout_marginBottom="1dp"
android:layout_marginRight="52dp"
android:layout_alignParentRight="true"
android:layout_above="@id/channel6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel5"/>
</RelativeLayout>
<!-- 二级菜单 -->
<RelativeLayout
android:id="@+id/level2_Rl"
android:layout_width="140dp"
android:layout_height="70dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" >
<ImageView
android:layout_marginLeft="3dp"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_search"/>
<ImageView
android:id="@+id/menu_Iv"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_menu"/>
<ImageView
android:id="@+id/myyouku_Iv"
android:layout_marginRight="3dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_myyouku"/>
</RelativeLayout>
<!-- 一级菜单 -->
<RelativeLayout
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1" >
<ImageView
android:id="@+id/home_Iv"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_home" />
</RelativeLayout>
</RelativeLayout>
猜你喜欢
- 1、本篇内容本文让大家掌握 springmvc 中异步处理请求,特别牛逼的一个功能,大家一定要掌握。2、看段代码,分析问题@Response
- MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力。如果你有使用 JDBC 或其他 相似框架的经验,你就明白条件地串联 SQL
- 本篇主要讲解SpringBoot当中使用Servlet三大组件,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学
- JPA的加锁机制有两种,乐观锁和悲观锁。乐观锁:乐观锁的特点在于认为数据冲突或者更新丢失等情况是很少发生的.当发生的时候,抛出异常和回滚就足
- 一、什么是封装?封装就是将属性私有化,提供公有的方法访问私有属性。做法就是:修改属性的可见性来限制对属性的访问,并为每个属性创建一对取值(g
- C#中添加窗口的步骤:1是添加窗口。2是在程序中使用new实例化窗口类对象,并显示窗口。1 添加窗口在解决方案管理器->主项目名称-&
- 本文实例讲述了java设置session过期时间的实现方法,分享给大家供大家参考。具体实现方法如下:1、Timeout in the dep
- launch我们经常用,今天来看看它是什么原理。建议: 食用本篇文章之前记得先食用Kotlin协程之createCoroutine和star
- 读取文本文件中的内容此示例读取文本文件的内容以使用 System.IO.File 选件类的静态方法 ReadAllText 和 ReadAl
- java 网络编程java.net 类 InetAddress 此类表示互联网协议 (IP) 地址。 会抛出异常 UnknownHostEx
- Zuul作为网关服务,是其他各服务对外中转站,通过Zuul进行请求转发。这就涉及到部分数据是不能原封返回的,比如服务之间通信的凭证,用户的加
- 前言本文主要给大家介绍了关于Spring Boot应用极速部署脚本的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧
- 本文实例为大家分享了java抓取邮箱号码的具体代码,供大家参考,具体内容如下java抓取文件中邮箱号码的具体代码package reg;im
- Java的NIO中的管道,就类似于实际中的管道,有两端,一段作为输入,一段作为输出。也就是说,在创建了一个管道后,既可以对管道进行写,也可以
- 本文实例讲述了JFreeChart插件实现的折线图效果。分享给大家供大家参考,具体如下:package com.lei.jfreechart
- 我想到使用Redis的订阅发布模式是用来解决推送问题的~。对于概念性的叙述,多多少少还是要提一下的:什么是Redis发布订阅?Redis发布
- 面向对象三要素:封装、继承、多态。封装和继承,这两个比较好理解,但要理解多态的话,可就稍微有点难度了。今天,我们就来讲讲多态的理解。我们应该
- 问题描述这里我想测试某个与springboot相关的问题,结果在搭建mybatis时,发现没有成功从数据库中获取数据,报错信息为com.my
- 概述在Compose中,图片组件主要有两种,分别是显示图标的Icon组件和显示图片的Image组件,当我们显示一系列的小图标的时候,我们可以
- 实现系统重启的APK需要system的权限,在AndroidManifest.xml中增加android:sharedUserId=&quo