中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

建設(shè)綜合信息網(wǎng)站需要多少錢(qián)如何廣告推廣

建設(shè)綜合信息網(wǎng)站需要多少錢(qián),如何廣告推廣,外國(guó)做ppt的網(wǎng)站,中國(guó)十大電商排行榜Bilibili移動(dòng)端APP簡(jiǎn)介依賴效果登錄效果WebView自定義TobRow的Indicator大小首頁(yè)推薦LazyGridView使用Paging3熱門(mén)排行榜搜索模糊搜索富文本搜索結(jié)果視頻詳情合集信息Coroutines進(jìn)行網(wǎng)絡(luò)請(qǐng)求管理,避免回調(diào)地獄添加suspendwithContextGit項(xiàng)目鏈接末簡(jiǎn)介 此Demo采用A…

Bilibili移動(dòng)端APP

  • 簡(jiǎn)介
  • 依賴
  • 效果
  • 登錄
    • 效果
    • WebView
  • 自定義TobRow的Indicator大小
  • 首頁(yè)
    • 推薦
    • LazyGridView使用Paging3
    • 熱門(mén)
  • 排行榜
  • 搜索
    • 模糊搜索
      • 富文本
  • 搜索結(jié)果
  • 視頻詳情
    • 合集
  • 信息
  • Coroutines進(jìn)行網(wǎng)絡(luò)請(qǐng)求管理,避免回調(diào)地獄
    • 添加suspend
    • withContext
  • Git項(xiàng)目鏈接

簡(jiǎn)介

此Demo采用Android Compose聲明式UI編寫(xiě)而成,主體采用MVVM設(shè)計(jì)框架,Demo涉及到的主要技術(shù)包括:Flow、Coroutines、Retrofit、Okhttp、Hilt以及適配了深色模式等;主要數(shù)據(jù)來(lái)源于Bilibili API。

依賴

Demo中所使用的依賴如下表格所示

庫(kù)名稱備注
Flow
Coroutines協(xié)程
Retrofit網(wǎng)絡(luò)
Okhttp網(wǎng)絡(luò)
Hilt依賴注入
room數(shù)據(jù)存儲(chǔ)
coil異步加載圖片
paging分頁(yè)加載
media3-exoplayer視頻

效果

登錄

登錄在Demo中分為WebView嵌入B站網(wǎng)頁(yè)實(shí)現(xiàn)獲取Cookie和自主實(shí)現(xiàn)登錄,由于后者需要通過(guò)極驗(yàn)API驗(yàn)證,所以暫且采用前者獲取Cookie,后者繪制了基本view和基本邏輯

效果

WebView

由于登錄暫未實(shí)現(xiàn),故而此處就介紹使用WebView獲取Cookie。由于在Compose中并未直接提供WebView組件,故使用AndroidView進(jìn)行引入。以下代碼對(duì)WebView進(jìn)行了一個(gè)簡(jiǎn)單的封裝,我們只需要在onPageFinished方法中回調(diào)所獲的cookie即可,然后保存到緩存文件即可

@Composable
fun CustomWebView(modifier: Modifier = Modifier,url:String,onBack: (webView: WebView?) -> Unit,onProgressChange: (progress:Int)->Unit = {},initSettings: (webSettings: WebSettings?) -> Unit = {},onReceivedError: (error: WebResourceError?) -> Unit = {},onCookie:(String)->Unit = {}
){val webViewChromeClient = object: WebChromeClient(){override fun onProgressChanged(view: WebView?, newProgress: Int) {//回調(diào)網(wǎng)頁(yè)內(nèi)容加載進(jìn)度onProgressChange(newProgress)super.onProgressChanged(view, newProgress)}}val webViewClient = object: WebViewClient(){override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {super.onPageStarted(view, url, favicon)onProgressChange(-1)}override fun onPageFinished(view: WebView?, url: String?) {super.onPageFinished(view, url)onProgressChange(100)//監(jiān)聽(tīng)獲取cookieval cookie = CookieManager.getInstance().getCookie(url)cookie?.let{ onCookie(cookie) }}override fun shouldOverrideUrlLoading(view: WebView?,request: WebResourceRequest?): Boolean {if(null == request?.url) return falseval showOverrideUrl = request.url.toString()try {if (!showOverrideUrl.startsWith("http://")&& !showOverrideUrl.startsWith("https://")) {Intent(Intent.ACTION_VIEW, Uri.parse(showOverrideUrl)).apply {addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)view?.context?.applicationContext?.startActivity(this)}return true}}catch (e:Exception){return true}return super.shouldOverrideUrlLoading(view, request)}override fun onReceivedError(view: WebView?,request: WebResourceRequest?,error: WebResourceError?) {super.onReceivedError(view, request, error)onReceivedError(error)}}var webView:WebView? = nullval coroutineScope = rememberCoroutineScope()AndroidView(modifier = modifier,factory = { ctx ->WebView(ctx).apply {this.webViewClient = webViewClientthis.webChromeClient = webViewChromeClientinitSettings(this.settings)webView = thisloadUrl(url)}})BackHandler {coroutineScope.launch {onBack(webView)}}
}

自定義TobRow的Indicator大小

由于在compose中TobRow的指示器寬度被寫(xiě)死,如果需要更改指示器寬度,則需要自己進(jìn)行重寫(xiě),將源碼拷貝一份,然后根據(jù)自己需求進(jìn)行定制,具體代碼如下

@ExperimentalPagerApi
fun Modifier.customIndicatorOffset(pagerState: PagerState,tabPositions: List<TabPosition>,width: Dp
): Modifier = composed {if (pagerState.pageCount == 0) return@composed thisval targetIndicatorOffset: Dpval indicatorWidth: Dpval currentTab = tabPositions[minOf(tabPositions.lastIndex, pagerState.currentPage)]val targetPage = pagerState.targetPageval targetTab = tabPositions.getOrNull(targetPage)if (targetTab != null) {val targetDistance = (targetPage - pagerState.currentPage).absoluteValueval fraction = (pagerState.currentPageOffset / max(targetDistance, 1)).absoluteValuetargetIndicatorOffset = lerp(currentTab.left, targetTab.left, fraction)indicatorWidth = lerp(currentTab.width, targetTab.width, fraction).value.absoluteValue.dp} else {targetIndicatorOffset = currentTab.leftindicatorWidth = currentTab.width}fillMaxWidth().wrapContentSize(Alignment.BottomStart).padding(horizontal = (indicatorWidth - width) / 2).offset(x = targetIndicatorOffset).width(width)
}

使用就變得很簡(jiǎn)單了,因?yàn)槭遣捎胢odifier的擴(kuò)展函數(shù)進(jìn)行編寫(xiě),而modifier在每一個(gè)compose組件都擁有,所以只需要在tabrow的指示器調(diào)用即可,具體代碼如下

TabRow(...indicator = { pos ->TabRowDefaults.Indicator(color = BilibiliTheme.colors.tabSelect,modifier = Modifier.customIndicatorOffset(pagerState = pageState,tabPositions = pos,32.dp))}...)

首頁(yè)

整個(gè)首頁(yè)頁(yè)面由BottomNavbar構(gòu)成,包含四個(gè)子界面,其中第一個(gè)界面又由兩個(gè)子界面組成,通過(guò)TabRow+HorizontalPager完成子頁(yè)面滑動(dòng),子頁(yè)面分為推薦熱門(mén)兩個(gè)頁(yè)面

推薦

推薦頁(yè)面由上面的Banner和下方的LazyGridView組成,由于Compose中不允許同向滑動(dòng),所以就將Banner作為L(zhǎng)azyGridView的一個(gè)item,進(jìn)而進(jìn)行包裹

LazyGridView使用Paging3

由于在現(xiàn)在Compose版本中LazyGridView并不支持Paging3,所以如果有此類需求,則需要自己動(dòng)手,具體代碼如下

fun <T : Any> LazyGridScope.items(items: LazyPagingItems<T>,key: ((item: T) -> Any)? = null,span: ((item: T) -> GridItemSpan)? = null,contentType: ((item: T) -> Any)? = null,itemContent: @Composable LazyGridItemScope.(value: T?) -> Unit
) {items(count = items.itemCount,key = if (key == null) null else { index ->val item = items.peek(index)if (item == null) {//PagingPlaceholderKey(index)} else {key(item)}},span = if (span == null) null else { index ->val item = items.peek(index)if (item == null) {GridItemSpan(1)} else {span(item)}},contentType = if (contentType == null) {{ null }} else { index ->val item = items.peek(index)if (item == null) {null} else {contentType(item)}}) { index ->itemContent(items[index])}
}

熱門(mén)

熱門(mén)頁(yè)面代碼與推薦頁(yè)面代碼類似,此處不在闡述

排行榜

排行界面與上述類似,Tab+HorizontalPager完成所有子頁(yè)面滑動(dòng)切換,此處也不在繼續(xù)闡述

搜索

搜索界面主要分為四個(gè)模塊:搜索欄、熱搜內(nèi)容、搜索記錄、搜索列表;搜索框內(nèi)字符改變,搜索列表顯示并以富文本顯示,熱搜內(nèi)容展開(kāi)與折疊、搜索記錄內(nèi)容展開(kāi)與折疊、清空記錄等操作都在ViewModel中完成,然后view通過(guò)監(jiān)聽(tīng)VM中狀態(tài)值進(jìn)行重組

模糊搜索

在搜索框內(nèi)鍵入字符,然后通過(guò)字符的改變,獲取相應(yīng)的網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù),最后通過(guò)AnimatedVisibility顯示與隱藏搜索建議列表

富文本

通過(guò)逐字匹配輸入框內(nèi)的字符與搜索建議item內(nèi)容,然后輸入框的字符存在搜索建議列表中的文字就加入高亮顯示列表中,因?yàn)椴捎?code>buildAnnotatedString,可以讓文本顯示多種不同風(fēng)格,所以最后將字符內(nèi)容區(qū)別為高亮顏色和普通文本兩種文本,并讓其進(jìn)行顯示

@Composable
fun RichText(selectColor: Color,unselectColor: Color,fontSize:TextUnit = TextUnit.Unspecified,searchValue: String,matchValue: String
){val richText = buildAnnotatedString {repeat(matchValue.length){val index = if (it < searchValue.length) matchValue.indexOf(searchValue[it]) else -1if (index == -1){withStyle(style = SpanStyle(fontSize = fontSize,color = unselectColor,)){append(matchValue[it])}}else{withStyle(style = SpanStyle(fontSize = fontSize,color = selectColor,)){append(matchValue[index])}}}}Text(text = richText,maxLines = 1,overflow = TextOverflow.Ellipsis,modifier = Modifier.fillMaxWidth(),)
}

搜索結(jié)果

搜索結(jié)果也是由ScrollableTabRow+HorizontalPager完成子頁(yè)面的滑動(dòng)切換,但是與上述不同的是,所展現(xiàn)的Tab與內(nèi)容并不是固定,而是根據(jù)后端返回的數(shù)據(jù)進(jìn)行自動(dòng)生成的。由于其他子頁(yè)面的內(nèi)容都是由LazyColumn進(jìn)行展現(xiàn),而綜合界面有需要將其他界面的數(shù)據(jù)進(jìn)行集中,所以就必須LazyColumn嵌套LazyColumn,然后這在Compose中是不被允許的,所以就將子Page的LazyColumn,使用modifier.heightIn(max = screenHeight.dp)進(jìn)行高度限制,高度可以取屏幕高度,并且多個(gè)item之間都是取屏幕高度,之間不會(huì)存在間隙

視頻詳情

視頻播放功能暫未實(shí)現(xiàn)完成,因?yàn)楂@取的API返回的URL進(jìn)行播放一直為403,被告知權(quán)限不足,在網(wǎng)上進(jìn)行多番查詢未果,所以暫且擱置。視頻庫(kù)采用的Google的ExoPlayer

合集

每個(gè)視頻返回的內(nèi)容數(shù)據(jù)格式一致,但具體內(nèi)容不一致,有的視頻存在排行信息、合集等,就通過(guò)AnimatedVisibility進(jìn)行顯示和隱藏,將所有結(jié)果進(jìn)行列出,然后在ViewModel通過(guò)解析數(shù)據(jù),并改變相應(yīng)的狀態(tài)值,view即可進(jìn)行重組

信息

Coroutines進(jìn)行網(wǎng)絡(luò)請(qǐng)求管理,避免回調(diào)地獄

在日常開(kāi)發(fā)中網(wǎng)絡(luò)請(qǐng)求必不可少,在傳統(tǒng)View+java開(kāi)發(fā)中使用Retrifit或者okhttp進(jìn)行網(wǎng)絡(luò)請(qǐng)求最為常見(jiàn),但大多數(shù)場(chǎng)景中,后一個(gè)API需要前一個(gè)API數(shù)據(jù)內(nèi)字段值,此時(shí)就需要callback進(jìn)行操作,回調(diào)一次獲取代碼依舊看起來(lái)簡(jiǎn)潔,可讀,但次數(shù)一旦增多,則會(huì)掉入回調(diào)地獄。Google后續(xù)推出的協(xié)程完美解決此類問(wèn)題,協(xié)程的主要核心就是“通過(guò)非阻塞的代碼實(shí)現(xiàn)阻塞功能”,具體代碼如下

添加suspend

以下為示例代碼,通過(guò)給接口添加suspend標(biāo)志符,告知外界次方法需要掛起

@GET("xxxxx")suspend fun getVideoDetail(@Query("aid")aid:Int):BaseResponse<VideoDetail>

withContext

getVideoDetail掛起函數(shù)返回一個(gè)字段值,然后通過(guò)withContext包裹,使其進(jìn)行阻塞,然后將返回值進(jìn)行返回,后續(xù)的getVideoUrl掛起函數(shù)就可以使用前一個(gè)接口返回的數(shù)據(jù);需要注意的是,函數(shù)都需為suspend修飾的方法,并且在統(tǒng)一協(xié)程域中,否則會(huì)出現(xiàn)異常

 viewModelScope.launch(Dispatchers.Main) {try {withContext(Dispatchers.Main){val cid = withContext(Dispatchers.IO){getVideoDetail(_videoState.value.aid)}val url = withContext(Dispatchers.IO){getVideoUrl(avid = _videoState.value.aid, cid = cid)}if (url.isNotEmpty()){play(url)}getRelatedVideos(_videoState.value.aid)}}catch (e:Exception){Log.d("VDetailViewModel",e.message.toString())}}

Git項(xiàng)目鏈接

Git項(xiàng)目鏈接

此Demo并未完全完善,尤其是播放界面,由于采用Bilibili API獲取的視頻URL,在播放時(shí)一直返回403錯(cuò)誤,被告知沒(méi)有權(quán)限,在根據(jù)文檔進(jìn)行使用以及網(wǎng)上查詢未果之后,只能暫且擱置此功能。

http://www.risenshineclean.com/news/42349.html

相關(guān)文章:

  • 國(guó)產(chǎn)一級(jí)a做爰片免費(fèi)網(wǎng)站哪個(gè)網(wǎng)站是免費(fèi)的
  • 網(wǎng)絡(luò)營(yíng)銷模式包括哪些seo網(wǎng)站關(guān)鍵詞快速排名
  • 做網(wǎng)站放太多視頻seo項(xiàng)目分析
  • 十堰網(wǎng)站seo方法百度seo關(guān)鍵詞優(yōu)化公司
  • 做公司網(wǎng)站一般多少錢(qián)免費(fèi)軟件下載網(wǎng)站有哪些
  • 集團(tuán)網(wǎng)站建設(shè)方案書(shū)游戲推廣員是違法的嗎
  • 軟件開(kāi)發(fā)步驟流程鄭州見(jiàn)效果付費(fèi)優(yōu)化公司
  • 廈門(mén) 微網(wǎng)站制作企業(yè)推廣策劃書(shū)
  • 做寵物食品的網(wǎng)站優(yōu)化落實(shí)疫情防控新十條
  • 上傳了網(wǎng)站源碼怎么做新聞最新熱點(diǎn)
  • 桓臺(tái)網(wǎng)站開(kāi)發(fā)廣州:推動(dòng)優(yōu)化防控措施落地
  • 中國(guó)互聯(lián)網(wǎng)網(wǎng)站性能丈哥seo博客工具
  • 錦州網(wǎng)站建設(shè)多少錢(qián)網(wǎng)站排名掉了怎么恢復(fù)
  • wordpress 地址 .html臺(tái)州seo
  • 別人抄襲網(wǎng)站設(shè)計(jì)怎么辦設(shè)計(jì)師必備的6個(gè)網(wǎng)站
  • 尋花問(wèn)柳一家專注做男人喜愛(ài)的網(wǎng)站什么網(wǎng)站推廣比較好
  • 諸城盟族網(wǎng)站建設(shè)北京做網(wǎng)站公司哪家好
  • 網(wǎng)上營(yíng)銷活動(dòng)長(zhǎng)沙網(wǎng)站seo分析
  • 學(xué)校校園網(wǎng)站建設(shè)方案上海網(wǎng)站營(yíng)銷seo方案
  • 做圖片的網(wǎng)站外貿(mào)建站
  • 網(wǎng)站開(kāi)發(fā)研究背景域名搜索
  • 做網(wǎng)站 警察佛山抖音seo
  • macos做網(wǎng)站快速網(wǎng)站推廣
  • 網(wǎng)站開(kāi)發(fā)技術(shù)項(xiàng)目北京seo相關(guān)
  • 免費(fèi)做網(wǎng)站方案新手怎么做seo優(yōu)化
  • win2012 iis 部署網(wǎng)站運(yùn)營(yíng)是做什么的
  • 網(wǎng)站轉(zhuǎn)化分析百度優(yōu)化怎么做
  • 大連市建委官方網(wǎng)站推廣一般收多少錢(qián)
  • java python 做網(wǎng)站武漢seo認(rèn)可搜點(diǎn)網(wǎng)絡(luò)
  • 北京營(yíng)銷型網(wǎng)站建設(shè)價(jià)格西安百度推廣運(yùn)營(yíng)公司