美橙互联网站打不开,linux宝塔面板做网站,商丘网站制作软件,可以免费做网站吗文章目录 概述1 效果对比1.1 使用添加Item的办法#xff1a;1.2 使用自定义的方法 2. 效果实现2.1 列表为空时的提示页面实现2.2 添加Item的方式代码实现2.3 使用自定义的方式实现 3. UI工具类 概述
目前大多数的APP都会使用列表的方式来呈现内容#xff0c;例如淘宝#x… 文章目录 概述1 效果对比1.1 使用添加Item的办法1.2 使用自定义的方法 2. 效果实现2.1 列表为空时的提示页面实现2.2 添加Item的方式代码实现2.3 使用自定义的方式实现 3. UI工具类 概述
目前大多数的APP都会使用列表的方式来呈现内容例如淘宝京东腾讯体育的评论区等都会使用列表布局。在Android传统的View中主要是使用RecyclerView控件来实现大量数据的展示。而在Compose中使用的是LazyColumn或者是LazyGrid组件。这些组件的使用都很简单网上有很多的例子不是本文的重点本文的重点是介绍实现当我们需要展示的数据展示完了后即列表滑动到最底部的时候我们需要展示给用户一个提示信息比如”已经到底“。比如百度的评论区翻到最后一条时 在Compose 中这个需求其实也不难网上也有说明。做法就是在布局中多加一个item,用于展示最后的这条提示信息。而本文我会介绍另一种办法是我个人在写项目的时候琢磨出来的。感觉效果会好点。
1 效果对比
本文的UI图片展示如下 滑动到底部的时候会显示一条提示信息 ”哥我已经到底了!!!“ 1.1 使用添加Item的办法 1.2 使用自定义的方法 经过对比上面的两个动图我们可以发现使用添加Item的方法(也就是网上提供的办法)当我们快要滑动到底部的时候就会看到文字已经开始展示了感觉有点生硬给人的感觉就是提示信息是预埋在底部的。虽然也能完成需求而且也没啥不妥之处但我个人就是觉得不太舒服而第二种方式可以看到只有我们真正的滑动到这个LazyGrid的底部的时候提示信息才会展示。因为在上面的界面中们也发现了有个添加图片的悬浮按钮为了展示这个悬浮按钮我们是让内容和底部做了一定的内边距的。所以个人感觉当我们把整个LazyGrid滑完再展示信息的话才是符合逻辑的而不是还没滑动到底部的时候就看到了下面的提示信息 看完效果图接下来我们就分别介绍下两种实现方式吧需要的读者按需取用这里只介绍LazyGrid,LazyColumn的也是一样的所以不多做赘述。
2. 效果实现
2.1 列表为空时的提示页面实现
在列表展示内容的时候当列表中没有内容或者网络不可达导致无法获取到内容的时候往往会展示一个提示的页面本文也简单的实现了下读者可参考使用。界面效果如下 代码如下
Composable
fun ShowEmptyUI(topMargin: Dp) {Column(modifier Modifier.fillMaxHeight(),verticalArrangement Arrangement.Top,horizontalAlignment Alignment.CenterHorizontally) {Spacer(modifier Modifier.height(topMargin))Image(painter painterResource(R.drawable.no_content),contentDescription null,modifier Modifier.size(81.dp),contentScale ContentScale.Crop)Text(text 没有内容可以看啦,style TextStyle(fontSize TextUnit(16f, TextUnitType.Sp),color Color(0xFFE0E6EC),),modifier Modifier.height(22.dp))}
}2.2 添加Item的方式代码实现
添加Item的方式很简单就是在LazyGrid的block语句块中的最下面添加如下的代码
item(span {GridItemSpan(maxLineSpan)}) {Text(text 哥,我已经到底了!!!,style TextStyle(fontSize TextUnit(14f, TextUnitType.Sp),color Color(0xFF92989E)),modifier Modifier.fillMaxWidth(),textAlign TextAlign.Center)}即可实现滑动到底部时展示提示信息的需求但是这中方式好像无法做定制比如我想控制提示信息动态显示隐藏好像无法做到发现能做到的读者欢迎评论区讨论哈。 完整代码为
// dataList的定义
val dataList mutableListOfInt(R.drawable.m,R.drawable.m1,R.drawable.m2,R.drawable.m3,R.drawable.m4,R.drawable.m5,R.drawable.m6,R.drawable.m7,R.drawable.m8,R.drawable.m9,R.drawable.m10
)// 图片资源文件下的图片读者可以替换为自己的图片。
Composable
fun ShowGridDemoUIByItem() {if (dataList.isEmpty()) {ShowEmptyUI(topMargin 211.dp)} else {val lazyGridState rememberLazyGridState()LazyVerticalGrid(state lazyGridState,columns GridCells.Fixed(2),contentPadding PaddingValues(start 15.dp,top 10.dp,end 16.dp,bottom 161.dp),verticalArrangement Arrangement.spacedBy(12.dp),horizontalArrangement Arrangement.spacedBy(11.dp),modifier Modifier.background(Color(0xff31373d)).fillMaxWidth().fillMaxHeight()) {items(dataList, key { it.hashCode() }) {Image(painter painterResource(it),contentDescription null,contentScale ContentScale.Crop,modifier Modifier.size(200.dp).clip(shape RoundedCornerShape(14.dp)))}item(span {GridItemSpan(maxLineSpan)}) {Text(text 哥,我已经到底了!!!,style TextStyle(fontSize TextUnit(14f, TextUnitType.Sp),color Color(0xFF92989E)),modifier Modifier.fillMaxWidth(),textAlign TextAlign.Center)}}}
}
2.3 使用自定义的方式实现
自定义的方式就是在LazyGrid的基础上做扩展当我们使用LazyGrid组件时需要我们传入一个val lazyGridState rememberLazyGridState() 这个lazyGridState中保存了LazyGrid组件的很多状态信息比如当前的列表中第一个可见item的position,当前是否可以往前滑动是否可以往后滑动是否正在滚动以及布局信息等我们拿到这些信息后就可以做一些自己想要实现的动作了。本功能我们就可以通过lazyGridState拿到当前是否可以继续往前滑动如果不能则证明滑动到底部了。API为
val canScrollBack lazyGridState.canScrollBackward然后通过布局信息拿到对应的内容后的内边距网格布局的宽和网格布局的末端偏移量然后计算出我们要展示的提示文字的显示位置。API为
// 这个值就是我们设置的 bottom 161.dp 中的161.dp的像素值/*
LazyVerticalGrid(state lazyGridState,columns GridCells.Fixed(2),contentPadding PaddingValues(start 15.dp,top 10.dp,end 16.dp,bottom 161.dp)......*/val afterPending layoutInfo.value.afterContentPaddingval gridViewEndOffset layoutInfo.value.viewportEndOffset.toFloat()val gridViewW layoutInfo.value.viewportSize.width.toFloat()由于本案例中文字需要居中展示所以我们还需要测量出文字的宽度。使用Paint的API测量 val paint TextPaint().apply {textSize UIUtils.sp2px(context, 14f)}val bottomText 哥,我已经到底了!!!val textW paint.measureText(bottomText)接着就可以计算提示文字的展示位置了如下所示
// 最后一个Item和提示的距离val bottomMargin UIUtils.dp2px(context,18f)val xOffset (gridViewW / 2 - textW / 2)val yOffset gridViewEndOffset - afterPending bottomMargin最后使用Modifier的drawBehind API将文字绘制出来就行了。 modifier Modifier.background(Color(0xff31373d)).fillMaxWidth().fillMaxHeight().drawBehind {...if (!canScrollForward) {drawText(textMeasurer textMeasurer,text bottomText,style TextStyle(fontSize TextUnit(14f, TextUnitType.Sp),color Color(0xFF92989E)),softWrap false,topLeft Offset(x xOffset, y yOffset))}...}完整的代码为
OptIn(ExperimentalTextApi::class)
Composable
fun ShowGridDemoUI() {if (dataList.isEmpty()) {ShowEmptyUI(topMargin 211.dp)} else {val lazyGridState rememberLazyGridState()val firstVisibleItemIndex by remember {derivedStateOf { lazyGridState.firstVisibleItemIndex }}val canScrollForward lazyGridState.canScrollForwardval canScrollBack lazyGridState.canScrollBackwardval inInScrolling lazyGridState.isScrollInProgressLog.d(TAG, firstVisibleItemIndex $firstVisibleItemIndex, canScrollForward: $canScrollForward ,canScrollBack: $canScrollBack ,inInScrolling: $inInScrolling ,mediaFileList: size : ${dataList.size})val layoutInfo remember {derivedStateOf { lazyGridState.layoutInfo }}val context LocalContext.currentval textMeasurer rememberTextMeasurer(100)LazyVerticalGrid(state lazyGridState,columns GridCells.Fixed(2),contentPadding PaddingValues(start 15.dp,top 10.dp,end 16.dp,bottom 161.dp),verticalArrangement Arrangement.spacedBy(12.dp),horizontalArrangement Arrangement.spacedBy(11.dp),modifier Modifier.background(Color(0xff31373d)).fillMaxWidth().fillMaxHeight().drawBehind {val paint TextPaint().apply {textSize UIUtils.sp2px(context, 14f)}val afterPending layoutInfo.value.afterContentPaddingval gridViewEndOffset layoutInfo.value.viewportEndOffset.toFloat()val gridViewW layoutInfo.value.viewportSize.width.toFloat()val bottomText 哥,我已经到底了!!!val textW paint.measureText(bottomText)// 最后一个Item和提示的距离val bottomMargin UIUtils.dp2px(context,18f)val xOffset (gridViewW / 2 - textW / 2)val yOffset gridViewEndOffset - afterPending bottomMarginLog.d(TAG, xcy: canScrollForward: $canScrollForward ,xOffset:$xOffset ,yOffset: $yOffset, ,bottomMargin: $bottomMargin ,afterPending: $afterPending gridViewW:$gridViewW ,textW: $textW)if (!canScrollForward) {drawText(textMeasurer textMeasurer,text bottomText,style TextStyle(fontSize TextUnit(14f, TextUnitType.Sp),color Color(0xFF92989E)),softWrap false,topLeft Offset(x xOffset, y yOffset))}}) {items(dataList, key { it.hashCode() }) {Image(painter painterResource(it),contentDescription null,contentScale ContentScale.Crop,modifier Modifier.size(200.dp).clip(shape RoundedCornerShape(14.dp)))}}}
}3. UI工具类
object UIUtils {fun dp2px(context: Context, dpValue: Float): Float {return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpValue,context.resources.displayMetrics).toInt().toFloat()}fun px2dp(context: Context, pxValue: Float): Float {return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,pxValue,context.resources.displayMetrics).toInt().toFloat()}SuppressLint(InternalInsetResource, DiscouragedApi)fun getStatusBarHeight(context: Context): Int {val activity context as Activityval resId activity.resources.getIdentifier(status_bar_height, dimen, android)if (resId 0) {return activity.resources.getDimensionPixelSize(resId)}return 0}SuppressLint(InternalInsetResource, DiscouragedApi)fun getNavigationBarHeight(context: Context): Int {val activity context as Activityval resId activity.resources.getIdentifier(navigation_bar_height, dimen, android)if (resId 0) {return activity.resources.getDimensionPixelSize(resId)}return 0}fun sp2px(context: Context, spValue: Float): Float {return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spValue,context.resources.displayMetrics).toInt().toFloat()}fun px2sp(context: Context, spValue: Float): Float {return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,spValue,context.resources.displayMetrics).toInt().toFloat()}
}