CustomBottomBarTV.kt 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. package com.vpn.fastestvpnservice.navigation
  2. import android.util.Log
  3. import androidx.activity.ComponentActivity
  4. import androidx.compose.foundation.background
  5. import androidx.compose.foundation.clickable
  6. import androidx.compose.foundation.focusable
  7. import androidx.compose.foundation.layout.Arrangement
  8. import androidx.compose.foundation.layout.Box
  9. import androidx.compose.foundation.layout.Row
  10. import androidx.compose.foundation.layout.fillMaxSize
  11. import androidx.compose.foundation.layout.fillMaxWidth
  12. import androidx.compose.foundation.layout.height
  13. import androidx.compose.foundation.layout.padding
  14. import androidx.compose.foundation.layout.size
  15. import androidx.compose.material.Surface
  16. import androidx.compose.material3.Icon
  17. import androidx.compose.material3.MaterialTheme
  18. import androidx.compose.material3.Scaffold
  19. import androidx.compose.runtime.Composable
  20. import androidx.compose.runtime.LaunchedEffect
  21. import androidx.compose.runtime.MutableState
  22. import androidx.compose.runtime.getValue
  23. import androidx.compose.runtime.mutableIntStateOf
  24. import androidx.compose.runtime.mutableStateOf
  25. import androidx.compose.runtime.remember
  26. import androidx.compose.runtime.setValue
  27. import androidx.compose.ui.Alignment
  28. import androidx.compose.ui.Modifier
  29. import androidx.compose.ui.draw.alpha
  30. import androidx.compose.ui.focus.FocusRequester
  31. import androidx.compose.ui.focus.focusRequester
  32. import androidx.compose.ui.focus.onFocusChanged
  33. import androidx.compose.ui.graphics.Color
  34. import androidx.compose.ui.res.colorResource
  35. import androidx.compose.ui.res.painterResource
  36. import androidx.compose.ui.unit.dp
  37. import androidx.navigation.NavGraph.Companion.findStartDestination
  38. import androidx.navigation.NavHostController
  39. import androidx.navigation.compose.currentBackStackEntryAsState
  40. import androidx.navigation.compose.rememberNavController
  41. import com.vpn.fastestvpnservice.R
  42. import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
  43. val screens = listOf(
  44. BottomBarScreen.Home,
  45. BottomBarScreen.Settings,
  46. BottomBarScreen.Help,
  47. BottomBarScreen.Account
  48. )
  49. var isHomeScreenPressed: MutableState<Boolean> = mutableStateOf(true)
  50. var isSettingsScreenPressed: MutableState<Boolean> = mutableStateOf(false)
  51. var isHelpScreenPressed: MutableState<Boolean> = mutableStateOf(false)
  52. var isAccountScreenPressed: MutableState<Boolean> = mutableStateOf(false)
  53. var selectedItemIndex: MutableState<Int> = mutableIntStateOf(0)
  54. var isFirstItemPressed: MutableState<Boolean> = mutableStateOf(false)
  55. var isSecondItemPressed: MutableState<Boolean> = mutableStateOf(false)
  56. var isThirdItemPressed: MutableState<Boolean> = mutableStateOf(false)
  57. var isFourthItemPressed: MutableState<Boolean> = mutableStateOf(false)
  58. var isFirstItemFocused: MutableState<Boolean> = mutableStateOf(false)
  59. var isSecondItemFocused: MutableState<Boolean> = mutableStateOf(false)
  60. var isThirdItemFocused: MutableState<Boolean> = mutableStateOf(false)
  61. var isFourthItemFocused: MutableState<Boolean> = mutableStateOf(false)
  62. @Composable
  63. fun CustomBottomBarTV(navHostController: NavHostController, activity: ComponentActivity) {
  64. val navController1 = rememberNavController()
  65. var isBottomBarVisible by remember { mutableStateOf(true) }
  66. // var selectedItemIndex by remember { mutableIntStateOf(0) }
  67. var focusRequestersList = remember { List(screens.size) { FocusRequester() } }
  68. navController1.addOnDestinationChangedListener { _,_,_ ->
  69. isBottomBarVisible = navController1.currentDestination?.route in listOf(
  70. screens[0].route, screens[1].route, screens[2].route, screens[3].route)
  71. }
  72. Scaffold (
  73. modifier = Modifier.fillMaxSize(),
  74. bottomBar = {
  75. if (isBottomBarVisible) {
  76. BottomBarNavTV(
  77. navHostController = navController1,
  78. screens = screens
  79. )
  80. }
  81. },
  82. content = { padding ->
  83. Box(modifier = Modifier.padding(padding)) {
  84. BottomBarNavGraphTV(
  85. navHostController = navController1,
  86. settingsNavHostController = navHostController,
  87. activity
  88. )
  89. }
  90. }
  91. )
  92. }
  93. @Composable
  94. fun BottomBarNavTV(
  95. navHostController: NavHostController,
  96. screens: List<BottomBarScreen>
  97. ) {
  98. // var isFirstItemFocused by remember { mutableStateOf(false) }
  99. // var isSecondItemFocused by remember { mutableStateOf(false) }
  100. // var isThirdItemFocused by remember { mutableStateOf(false) }
  101. // var isFourthItemFocused by remember { mutableStateOf(false) }
  102. val focusRequester1 = remember { FocusRequester() }
  103. val focusRequester2 = remember { FocusRequester() }
  104. val focusRequester3 = remember { FocusRequester() }
  105. val focusRequester4 = remember { FocusRequester() }
  106. var isClicked by remember { mutableStateOf(false) }
  107. val navBackStackEntry = navHostController.currentBackStackEntryAsState()
  108. var currentDestination = navBackStackEntry.value?.destination
  109. var screen: BottomBarScreen = BottomBarScreen.Home
  110. val topPadding = 5.dp
  111. when (selectedItemIndex.value) {
  112. 0 -> {
  113. screen = BottomBarScreen.Home
  114. }
  115. 1 -> {
  116. screen = BottomBarScreen.Settings
  117. }
  118. 2 -> {
  119. screen = BottomBarScreen.Help
  120. }
  121. 3 -> {
  122. screen = BottomBarScreen.Account
  123. }
  124. }
  125. if (isClicked) {
  126. Log.d("test_bottom_navbar",
  127. "Before:: currentDestination -> " + currentDestination?.route + " -> " + screen.route + " " + selectedItemIndex.value
  128. )
  129. if (currentDestination?.route != screen.route) {
  130. Log.d("test_bottom_navbar",
  131. "currentDestination -> " + currentDestination?.route
  132. + "Screen Clicked -> " + screen.route
  133. )
  134. LaunchedEffect(Unit) {
  135. navHostController.navigate(screen.route)
  136. {
  137. popUpTo(
  138. navHostController.graph
  139. .findStartDestination().id) {
  140. saveState = true
  141. }
  142. launchSingleTop = true
  143. }
  144. }
  145. }
  146. isClicked = false
  147. }
  148. if (isFirstItemPressed.value) {
  149. LaunchedEffect(key1 = Unit) {
  150. focusRequester1.requestFocus()
  151. }
  152. isFirstItemPressed.value = false
  153. }
  154. if (isSecondItemPressed.value) {
  155. LaunchedEffect(key1 = Unit) {
  156. focusRequester2.requestFocus()
  157. }
  158. isSecondItemPressed.value = false
  159. }
  160. if (isThirdItemPressed.value) {
  161. LaunchedEffect(key1 = Unit) {
  162. focusRequester3.requestFocus()
  163. }
  164. isThirdItemPressed.value = false
  165. }
  166. if (isFourthItemPressed.value) {
  167. LaunchedEffect(key1 = Unit) {
  168. focusRequester4.requestFocus()
  169. }
  170. isFourthItemPressed.value = false
  171. }
  172. Box(
  173. modifier = Modifier
  174. .fillMaxWidth()
  175. .background(MaterialTheme.colorScheme.background),
  176. contentAlignment = Alignment.Center
  177. ) {
  178. val iconSize = 45.dp
  179. Row(
  180. modifier = Modifier
  181. .height(55.dp)
  182. .fillMaxWidth(fraction = 0.4f)
  183. .padding(horizontal = 0.dp)
  184. .background(MaterialTheme.colorScheme.background),
  185. horizontalArrangement = Arrangement.SpaceBetween,
  186. verticalAlignment = Alignment.CenterVertically
  187. ) {
  188. Surface(
  189. color = if (isFirstItemFocused.value) MaterialTheme.colorScheme.outline
  190. else MaterialTheme.colorScheme.background,
  191. modifier = Modifier
  192. .focusRequester(focusRequester1)
  193. .onFocusChanged {
  194. Log.d("is_focused", "1st")
  195. isFirstItemFocused.value = it.isFocused
  196. if (it.isFocused) {
  197. Log.d("is_focused", "1st if")
  198. selectedItemIndex.value = 0
  199. isClicked = true
  200. }
  201. }
  202. .focusable()
  203. .clickable {
  204. isHomeScreenPressed.value = true
  205. }
  206. ) {
  207. val color = if (selectedItemIndex.value == 0) colorResource(id = R.color.blue_text)
  208. else MaterialTheme.colorScheme.primary
  209. val alpha = if (selectedItemIndex.value == 0) 1f else 0.5f
  210. Icon(
  211. painter = painterResource(id = screens[0].icon),
  212. contentDescription = "Navigation Icon",
  213. tint = color,
  214. modifier = Modifier
  215. .size(iconSize)
  216. .padding(top = topPadding, bottom = 4.dp)
  217. .alpha(alpha)
  218. )
  219. }
  220. Surface(
  221. color = if (isSecondItemFocused.value) MaterialTheme.colorScheme.outline
  222. else MaterialTheme.colorScheme.background,
  223. modifier = Modifier
  224. .focusRequester(focusRequester2)
  225. .onFocusChanged {
  226. Log.d("is_focused", "2nd")
  227. isSecondItemFocused.value = it.isFocused
  228. if (it.isFocused) {
  229. Log.d("is_focused", "2nd if")
  230. selectedItemIndex.value = 1
  231. isClicked = true
  232. }
  233. }
  234. .focusable()
  235. .clickable {
  236. isSettingsScreenPressed.value = true
  237. }
  238. ) {
  239. val color = if (selectedItemIndex.value == 1) colorResource(id = R.color.blue_text)
  240. else MaterialTheme.colorScheme.primary
  241. val alpha = if (selectedItemIndex.value == 1) 1f else 0.5f
  242. Icon(
  243. painter = painterResource(id = screens[1].icon),
  244. contentDescription = "Navigation Icon",
  245. tint = color,
  246. modifier = Modifier
  247. .size(iconSize)
  248. .padding(top = topPadding, bottom = 4.dp)
  249. .alpha(alpha)
  250. )
  251. }
  252. Surface(
  253. color = if (isThirdItemFocused.value) MaterialTheme.colorScheme.outline
  254. else MaterialTheme.colorScheme.background,
  255. modifier = Modifier
  256. .focusRequester(focusRequester3)
  257. .onFocusChanged {
  258. Log.d("is_focused", "3rd")
  259. isThirdItemFocused.value = it.isFocused
  260. if (it.isFocused) {
  261. Log.d("is_focused", "3rd if")
  262. selectedItemIndex.value = 2
  263. isClicked = true
  264. }
  265. }
  266. .focusable()
  267. .clickable {
  268. isHelpScreenPressed.value = true
  269. }
  270. ) {
  271. val color = if (selectedItemIndex.value == 2) colorResource(id = R.color.blue_text)
  272. else MaterialTheme.colorScheme.primary
  273. val alpha = if (selectedItemIndex.value == 2) 1f else 0.5f
  274. Icon(
  275. painter = painterResource(id = screens[2].icon),
  276. contentDescription = "Navigation Icon",
  277. tint = color,
  278. modifier = Modifier
  279. .size(iconSize)
  280. .padding(top = topPadding, bottom = 4.dp)
  281. .alpha(alpha)
  282. )
  283. }
  284. Surface(
  285. color = if (isFourthItemFocused.value) MaterialTheme.colorScheme.outline
  286. else MaterialTheme.colorScheme.background,
  287. modifier = Modifier
  288. .focusRequester(focusRequester4)
  289. .onFocusChanged {
  290. Log.d("is_focused", "4th")
  291. isFourthItemFocused.value = it.isFocused
  292. if (it.isFocused) {
  293. Log.d("is_focused", "4th if")
  294. selectedItemIndex.value = 3
  295. isClicked = true
  296. }
  297. }
  298. .focusable()
  299. .clickable {
  300. isAccountScreenPressed.value = true
  301. }
  302. ) {
  303. val color = if (selectedItemIndex.value == 3) colorResource(id = R.color.blue_text)
  304. else MaterialTheme.colorScheme.primary
  305. val alpha = if (selectedItemIndex.value == 3) 1f else 0.5f
  306. Icon(
  307. painter = painterResource(id = screens[3].icon),
  308. contentDescription = "Navigation Icon",
  309. tint = color,
  310. modifier = Modifier
  311. .size(iconSize)
  312. .padding(top = topPadding, bottom = 4.dp)
  313. .alpha(alpha)
  314. )
  315. }
  316. }
  317. }
  318. }