Commit 7a8f0345 authored by shohboz's avatar shohboz

add: dependencies, fragments, utils, di, navigation

parent de7b5205
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<component name="DesignSurface"> <component name="DesignSurface">
<option name="filePathToZoomLevelMap"> <option name="filePathToZoomLevelMap">
<map> <map>
<entry key="app/src/main/res/layout/activity_auth.xml" value="0.3416666666666667" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.22" /> <entry key="app/src/main/res/layout/activity_main.xml" value="0.22" />
</map> </map>
</option> </option>
......
plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'kotlin-android' id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
id 'androidx.navigation.safeargs.kotlin'
} }
android { android {
...@@ -40,7 +43,44 @@ dependencies { ...@@ -40,7 +43,44 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0' implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2' implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.+' testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
// Navigation
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2")
implementation "androidx.hilt:hilt-lifecycle-viewmodel:$hilt_jetpack_version"
kapt "androidx.hilt:hilt-compiler:$hilt_jetpack_version"
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
implementation 'com.makeramen:roundedimageview:2.3.0'
implementation("io.coil-kt:coil:1.4.0")
implementation 'com.airbnb.android:lottie:3.4.0'
debugImplementation "com.readystatesoftware.chuck:library:$chuck_version"
releaseImplementation "com.readystatesoftware.chuck:library-no-op:$chuck_version"
// SquareUp
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation "com.squareup.retrofit2:adapter-rxjava3:$retrofit_version"
implementation "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2"
// Lifecycle ViewModel LiveData
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$live_data_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$live_data_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$live_data_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$live_data_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$live_data_version"
implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$live_data_version"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'com.nabinbhandari.android:permissions:3.8'
} }
\ No newline at end of file
...@@ -2,17 +2,25 @@ ...@@ -2,17 +2,25 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="uz.ssd.mobiuz"> package="uz.ssd.mobiuz">
<uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.CALL_PHONE" />
<application <application
android:name=".app.App"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.MobiUzAndroid"> android:theme="@style/Theme.MobiUzAndroid"
android:usesCleartextTraffic="true">
<activity
android:name=".AuthActivity"
android:exported="false" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true"> android:configChanges="orientation"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
......
package uz.ssd.mobiuz
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class AuthActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_auth)
}
}
\ No newline at end of file
...@@ -4,9 +4,11 @@ import android.content.Intent ...@@ -4,9 +4,11 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
import dagger.hilt.android.AndroidEntryPoint
import uz.ssd.mobiuz.databinding.ActivityMainBinding import uz.ssd.mobiuz.databinding.ActivityMainBinding
import java.lang.NullPointerException import java.lang.NullPointerException
@AndroidEntryPoint
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private var _bn: ActivityMainBinding? = null private var _bn: ActivityMainBinding? = null
private val bn get() = _bn ?: throw NullPointerException("cannot inflate") private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
......
package uz.ssd.mobiuz.app
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class App : Application()
\ No newline at end of file
package uz.ssd.mobiuz.di
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
class DatabaseModule {
// @Provides
// @Singleton
// fun getDatabase(@ApplicationContext context: Context): AppDatabase =
// Room.databaseBuilder(context, AppDatabase::class.java,"block").build()
//
// @Provides
// @Singleton
// fun getProductDao(database: AppDatabase): ProductDao = database.productDao()
}
package uz.ssd.mobiuz.di
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface RepositoryModule {
// @Binds
// fun getMainRepository(repository: MainRepositoryImpl): MainRepository
//
// @Binds
// fun getAuthRepository(repository: AuthRepositoryImpl): AuthRepository
//
// @Binds
// fun getLocalRepository(repository: LocalRepositoryImpl): LocalRepository
}
\ No newline at end of file
package uz.ssd.mobiuz.di
import android.content.Context
import com.readystatesoftware.chuck.ChuckInterceptor
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import uz.ssd.mobiuz.model.SharedPref
import uz.ssd.mobiuz.network.api.ApiService
import uz.ssd.mobiuz.utils.CONSTANTS
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class ServerModule {
@Provides
@Singleton
fun getRetrofit(client: OkHttpClient): Retrofit = Retrofit.Builder()
.baseUrl(CONSTANTS.BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build()
@Provides
@Singleton
fun getApiService(retrofit: Retrofit): ApiService = retrofit.create(ApiService::class.java)
@Provides
@Singleton
fun getClient(@ApplicationContext context: Context, sharedPref: SharedPref): OkHttpClient = OkHttpClient.Builder()
.connectTimeout(60, java.util.concurrent.TimeUnit.SECONDS)
.readTimeout(60, java.util.concurrent.TimeUnit.SECONDS)
.addInterceptor(
ChuckInterceptor(context)
)
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
.addInterceptor(Interceptor { chain ->
val builder = chain.request().newBuilder()
builder.header("Content-Type", "application/x-www-form-urlencoded")
builder.header("Accept", "application/json")
builder.header("Authorization", "Bearer ${sharedPref.getUserToken()}")
chain.proceed(builder.build())
})
.build()
}
\ No newline at end of file
package uz.ssd.mobiuz.model
import android.content.Context
import android.content.SharedPreferences
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
class SharedPref @Inject constructor(@ApplicationContext context: Context) {
private var mySharedPref: SharedPreferences = context.getSharedPreferences("mvd", Context.MODE_PRIVATE)
fun setDeviceToken(token: String) {
mySharedPref.edit().putString("device_token", token).apply()
}
fun getDeviceToken(): String? {
return mySharedPref.getString("device_token", null)
}
fun setUserId(id: Int) {
mySharedPref.edit().putInt("user_id", id).apply()
}
fun getUserId(): Int {
return mySharedPref.getInt("user_id", 0)
}
fun setUserToken(token: String?) {
mySharedPref.edit().putString("user_token", token).apply()
}
fun getUserToken(): String? {
return mySharedPref.getString("user_token", null)
}
}
\ No newline at end of file
package uz.ssd.mobiuz.network.api
interface ApiService {
}
\ No newline at end of file
package uz.ssd.mobiuz.network.model
class ResponseList<T>(
var data: List<T>?,
var status: Status
)
package uz.ssd.mobiuz.network.model
class ResponseObject<T>(
var status: Status,
var data: T?
)
package uz.ssd.mobiuz.network.model
data class Status(
var message: String,
var code: Int
)
\ No newline at end of file
package uz.ssd.mobiuz.network.model
sealed class UiStateList<out T> {
data class SUCCESS<out T>(val data: List<T>) : UiStateList<T>()
data class ERROR(val message: String, var fromServer: Boolean = false) : UiStateList<Nothing>()
object LOADING : UiStateList<Nothing>()
object EMPTY : UiStateList<Nothing>()
}
\ No newline at end of file
package uz.ssd.mobiuz.network.model
sealed class UiStateObject<out T> {
data class SUCCESS<out T>(val data: T) : UiStateObject<T>()
data class ERROR(val message: String,var fromServer: Boolean = false) : UiStateObject<Nothing>()
object LOADING : UiStateObject<Nothing>()
object EMPTY : UiStateObject<Nothing>()
}
\ No newline at end of file
package uz.ssd.mobiuz.ui.auth
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import dagger.hilt.android.AndroidEntryPoint
import uz.ssd.mobiuz.R
import uz.ssd.mobiuz.databinding.FragmentVerificationBinding
import uz.ssd.mobiuz.ui.base.BaseFragment
import java.lang.NullPointerException
@AndroidEntryPoint
class LoginFragment : BaseFragment(R.layout.fragment_login) {
private var _bn: FragmentVerificationBinding? = null
private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
_bn = FragmentVerificationBinding.bind(view)
setUpUI()
collects()
}
override fun setUpUI() {
}
override fun collects() {
}
override fun onDestroy() {
_bn = null
super.onDestroy()
}
}
\ No newline at end of file
package uz.ssd.mobiuz.ui.auth
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import dagger.hilt.android.AndroidEntryPoint
import uz.ssd.mobiuz.R
import uz.ssd.mobiuz.databinding.FragmentVerificationBinding
import uz.ssd.mobiuz.ui.base.BaseFragment
import java.lang.NullPointerException
@AndroidEntryPoint
class RegisterFragment : BaseFragment(R.layout.fragment_register) {
private var _bn: FragmentVerificationBinding? = null
private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
_bn = FragmentVerificationBinding.bind(view)
setUpUI()
collects()
}
override fun setUpUI() {
}
override fun collects() {
}
override fun onDestroy() {
_bn = null
super.onDestroy()
}
}
\ No newline at end of file
package uz.ssd.mobiuz.ui.auth
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import dagger.hilt.android.AndroidEntryPoint
import uz.ssd.mobiuz.R
import uz.ssd.mobiuz.databinding.FragmentVerificationBinding
import uz.ssd.mobiuz.ui.base.BaseFragment
import java.lang.NullPointerException
@AndroidEntryPoint
class VerificationFragment : BaseFragment(R.layout.fragment_verification) {
private var _bn: FragmentVerificationBinding? = null
private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
_bn = FragmentVerificationBinding.bind(view)
setUpUI()
collects()
}
override fun setUpUI() {
}
override fun collects() {
}
override fun onDestroy() {
_bn = null
super.onDestroy()
}
}
package uz.ssd.mobiuz.ui.base
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import uz.ssd.mobiuz.R
abstract class BaseFragment(private val layoutId:Int) : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(layoutId,container,false)
}
protected abstract fun setUpUI()
protected abstract fun collects()
}
\ No newline at end of file
package uz.ssd.mobiuz.ui.home
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import dagger.hilt.android.AndroidEntryPoint
import uz.ssd.mobiuz.R
import uz.ssd.mobiuz.databinding.FragmentHomeBinding
import uz.ssd.mobiuz.databinding.FragmentVerificationBinding
import uz.ssd.mobiuz.ui.base.BaseFragment
import java.lang.NullPointerException
@AndroidEntryPoint
class HomeFragment : BaseFragment(R.layout.fragment_home) {
private var _bn: FragmentHomeBinding? = null
private val bn get() = _bn ?: throw NullPointerException("cannot inflate")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
_bn = FragmentHomeBinding.bind(view)
setUpUI()
collects()
}
override fun setUpUI() {
}
override fun collects() {
}
override fun onDestroy() {
_bn = null
super.onDestroy()
}
}
\ No newline at end of file
package uz.ssd.mobiuz.utils
object CONSTANTS {
const val BASE_URL = "http://157.230.7.9:9098/api/"
const val BASE_URL_WITHOUT_API = "http://157.230.7.9:9098"
const val IMAGE_URL = "http://157.230.7.9:9098/api/attach/"
const val IMAGE_URL_GET = "http://157.230.7.9:9098/api/attach/get/"
const val ROOM = "room"
const val RU = "ru"
const val UZ = "uz"
const val UZ_RU = "kv"
const val DES_POINT = "des_point"
const val TYPE_REPORT = "type_report"
const val TYPE_CREATE_SELF = "type_create_self"
const val TYPE_REPORT_102 = "type_report_102"
const val TYPE_REPORT_SELF = "type_report_self"
const val LOGO = "LOGO"
const val LONGITUDE = 69.2602108116081
const val LATITUDE = 41.34823322480444
const val LONGITUDE2 = 69.26776391206731
const val LATITUDE2 = 41.29976097420951
//history
const val INCIDENT_CARD = "INCIDENT_CARD"
const val CAMERA = "CAMERA"
const val SELF_EMPLOYMENT = "SELF_EMPLOYMENT"
const val ID_TASK = "ID_TASK"
const val TICKET_ID = "TICKET_ID"
}
\ No newline at end of file
package uz.ssd.mobiuz.utils
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.nabinbhandari.android.permissions.PermissionHandler
import com.nabinbhandari.android.permissions.Permissions
fun Fragment.checkPermission(permission: String, granted: () -> Unit) {
val mContext = context ?: return
val options = Permissions.Options()
options.setCreateNewTask(true)
Permissions.check(
mContext,
arrayOf(permission),
null,
options,
object : PermissionHandler() {
override fun onGranted() {
granted()
}
})
}
fun FragmentActivity.checkPermission(permission: String, granted: () -> Unit) {
val mContext = this
val options = Permissions.Options()
options.setCreateNewTask(true)
Permissions.check(
mContext,
arrayOf(permission),
null,
options,
object : PermissionHandler() {
override fun onGranted() {
granted()
}
})
}
fun Fragment.checkPermissions(permissions: Array<String>, granted: () -> Unit) {
val mContext = context ?: return
val options = Permissions.Options()
options.setCreateNewTask(true)
Permissions.check(
mContext,
permissions,
null,
options,
object : PermissionHandler() {
override fun onGranted() {
granted()
}
})
}
fun FragmentActivity.checkPermissions(permissions: Array<String>, granted: () -> Unit) {
val mContext = this
val options = Permissions.Options()
options.setCreateNewTask(true)
Permissions.check(
mContext,
permissions,
null,
options,
object : PermissionHandler() {
override fun onGranted() {
granted()
}
})
}
package uz.ssd.mobiuz.utils
import androidx.navigation.NavOptions
import uz.ssd.mobiuz.R
object Utils {
fun navOptions(): NavOptions {
return NavOptions.Builder()
.setEnterAnim(R.anim.slide_in_right)
.setExitAnim(R.anim.slide_out_left)
.setPopEnterAnim(R.anim.slide_in_left)
.setPopExitAnim(R.anim.slide_out_right)
.build()
}
}
\ No newline at end of file
/*
* Copyright 2019, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uz.ssd.mobiuz.utils.extensions
import android.content.Intent
import android.util.SparseArray
import androidx.core.util.forEach
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import com.google.android.material.bottomnavigation.BottomNavigationView
import uz.ssd.mobiuz.R
/**
* Manages the various graphs needed for a [BottomNavigationView].
*
* This sample is a workaround until the Navigation Component supports multiple back stacks.
*/
fun BottomNavigationView.setupWithNavController(
navGraphIds: List<Int>,
fragmentManager: FragmentManager,
containerId: Int,
intent: Intent
): LiveData<NavController> {
// Log.d("AAA","setupWithNavController")
// Map of tags
val graphIdToTagMap = SparseArray<String>()
// Result. Mutable live data with the selected controlled
val selectedNavController = MutableLiveData<NavController>()
var firstFragmentGraphId = 0
// First create a NavHostFragment for each NavGraph ID
navGraphIds.forEachIndexed { index, navGraphId ->
val fragmentTag = getFragmentTag(index)
// Find or create the Navigation host fragment
val navHostFragment = obtainNavHostFragment(
fragmentManager,
fragmentTag,
navGraphId,
containerId
)
// Obtain its id
val graphId = navHostFragment.navController.graph.id
if (index == 0) {
firstFragmentGraphId = graphId
}
// Save to the map
graphIdToTagMap[graphId] = fragmentTag
// Attach or detach nav host fragment depending on whether it's the selected item.
if (this.selectedItemId == graphId) {
// Update livedata with the selected graph
selectedNavController.value = navHostFragment.navController
attachNavHostFragment(fragmentManager, navHostFragment, index == 0)
} else {
detachNavHostFragment(fragmentManager, navHostFragment)
}
}
// Now connect selecting an item with swapping Fragments
var selectedItemTag = graphIdToTagMap[this.selectedItemId]
val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId]
var isOnFirstFragment = selectedItemTag == firstFragmentTag
// When a navigation item is selected
setOnNavigationItemSelectedListener { item ->
// Log.d("AAA","setOnNavigationItemSelectedListener")
// Don't do anything if the state is state has already been saved.
if (fragmentManager.isStateSaved) {
false
} else {
val newlySelectedItemTag = graphIdToTagMap[item.itemId]
if (selectedItemTag != newlySelectedItemTag) {
// Pop everything above the first fragment (the "fixed start destination")
fragmentManager.popBackStack(
firstFragmentTag,
FragmentManager.POP_BACK_STACK_INCLUSIVE
)
val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag)
as NavHostFragment
// Exclude the first fragment tag because it's always in the back stack.
if (firstFragmentTag != newlySelectedItemTag) {
// Commit a transaction that cleans the back stack and adds the first fragment
// to it, creating the fixed started destination.
fragmentManager.beginTransaction()
.setCustomAnimations(
R.anim.nav_default_enter_anim,
R.anim.nav_default_exit_anim,
R.anim.nav_default_pop_enter_anim,
R.anim.nav_default_pop_exit_anim
)
.attach(selectedFragment)
.setPrimaryNavigationFragment(selectedFragment)
.apply {
// Detach all other Fragments
graphIdToTagMap.forEach { _, fragmentTagIter ->
if (fragmentTagIter != newlySelectedItemTag) {
detach(fragmentManager.findFragmentByTag(firstFragmentTag)!!)
}
}
}
.addToBackStack(firstFragmentTag)
.setReorderingAllowed(true)
.commit()
}
selectedItemTag = newlySelectedItemTag
isOnFirstFragment = selectedItemTag == firstFragmentTag
selectedNavController.value = selectedFragment.navController
true
} else {
false
}
}
}
// Optional: on item reselected, pop back stack to the destination of the graph
setupItemReselected(graphIdToTagMap, fragmentManager)
// Handle deep link
setupDeepLinks(navGraphIds, fragmentManager, containerId, intent)
// Finally, ensure that we update our BottomNavigationView when the back stack changes
fragmentManager.addOnBackStackChangedListener {
// Log.d("AAA","addOnBackStackChangedListener")
if (!isOnFirstFragment && !fragmentManager.isOnBackStack(firstFragmentTag)) {
this.selectedItemId = firstFragmentGraphId
}
// Reset the graph if the currentDestination is not valid (happens when the back
// stack is popped after using the back button).
selectedNavController.value?.let { controller ->
if (controller.currentDestination == null) {
controller.navigate(controller.graph.id)
}
}
}
return selectedNavController
}
private fun BottomNavigationView.setupDeepLinks(
navGraphIds: List<Int>,
fragmentManager: FragmentManager,
containerId: Int,
intent: Intent
) {
// Log.d("AAA","setupDeepLinks")
navGraphIds.forEachIndexed { index, navGraphId ->
val fragmentTag = getFragmentTag(index)
// Find or create the Navigation host fragment
val navHostFragment = obtainNavHostFragment(
fragmentManager,
fragmentTag,
navGraphId,
containerId
)
// Handle Intent
if (navHostFragment.navController.handleDeepLink(intent)
&& selectedItemId != navHostFragment.navController.graph.id
) {
this.selectedItemId = navHostFragment.navController.graph.id
}
}
}
private fun BottomNavigationView.setupItemReselected(
graphIdToTagMap: SparseArray<String>,
fragmentManager: FragmentManager
) {
// Log.d("AAA","setupItemReselected")
setOnNavigationItemReselectedListener { item ->
val newlySelectedItemTag = graphIdToTagMap[item.itemId]
val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag)
as NavHostFragment
val navController = selectedFragment.navController
// Pop the back stack to the start destination of the current navController graph
navController.popBackStack(
navController.graph.startDestination, false
)
}
}
private fun detachNavHostFragment(
fragmentManager: FragmentManager,
navHostFragment: NavHostFragment
) {
// Log.d("AAA","detachNavHostFragment")
fragmentManager.beginTransaction()
.detach(navHostFragment)
.commitNow()
}
private fun attachNavHostFragment(
fragmentManager: FragmentManager,
navHostFragment: NavHostFragment,
isPrimaryNavFragment: Boolean
) {
// Log.d("AAA","attachNavHostFragment")
fragmentManager.beginTransaction()
.attach(navHostFragment)
.apply {
if (isPrimaryNavFragment) {
setPrimaryNavigationFragment(navHostFragment)
}
}
.commitNow()
}
private fun obtainNavHostFragment(
fragmentManager: FragmentManager,
fragmentTag: String,
navGraphId: Int,
containerId: Int
): NavHostFragment {
// Log.d("AAA","obtainNavHostFragment")
// If the Nav Host fragment exists, return it
val existingFragment = fragmentManager.findFragmentByTag(fragmentTag) as NavHostFragment?
existingFragment?.let { return it }
// Otherwise, create it and return it.
val navHostFragment = NavHostFragment.create(navGraphId)
fragmentManager.beginTransaction()
.add(containerId, navHostFragment, fragmentTag)
.commitNow()
return navHostFragment
}
private fun FragmentManager.isOnBackStack(backStackName: String): Boolean {
val backStackCount = backStackEntryCount
for (index in 0 until backStackCount) {
if (getBackStackEntryAt(index).name == backStackName) {
return true
}
}
// Log.d("AAA","isOnBackStack")
return false
}
private fun getFragmentTag(index: Int) = "bottomNavigation#$index"
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator">
<alpha
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.1" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<scale
android:duration="500"
android:fillAfter="true"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:cycles="7" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_longAnimTime"
android:fromYDelta="100%"
android:interpolator="@android:anim/decelerate_interpolator"
android:toYDelta="0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_longAnimTime"
android:fromYDelta="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toYDelta="-100%" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="@android:integer/config_mediumAnimTime"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
\ No newline at end of file
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="@android:integer/config_mediumAnimTime"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/translate"
android:animationOrder="normal"
android:delay="15%" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_longAnimTime"
android:fromYDelta="-100%"
android:interpolator="@android:anim/decelerate_interpolator"
android:toYDelta="0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_longAnimTime"
android:fromYDelta="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toYDelta="100%" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleX"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueTo="1.0"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleY"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueTo="1.0"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueTo="0dp"
android:valueType="floatType" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/overshoot_interpolator">
<scale
android:duration="600"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="100%"
android:pivotY="0%"
android:toXScale="1.0"
android:toYScale="1.0" />
<alpha
android:duration="600"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/overshoot_interpolator">
<scale
android:duration="600"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="100%"
android:pivotY="0%"
android:toXScale="0.0"
android:toYScale="0.0" />
<alpha
android:duration="600"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.3"
android:toYScale="1.3" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="-10"
android:toXDelta="10"
android:repeatCount="5"
android:repeatMode="reverse"
android:interpolator="@android:anim/linear_interpolator"
android:duration="70" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_shortAnimTime"
android:fromYDelta="0%p"
android:toYDelta="100%p" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="-100%"
android:interpolator="@android:anim/decelerate_interpolator"
android:toXDelta="0%" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="100%"
android:interpolator="@android:anim/decelerate_interpolator"
android:toXDelta="0%" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_shortAnimTime"
android:fromYDelta="100%p"
android:toYDelta="0%p" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromXDelta="0"
android:toYDelta="-100%" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="0%"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="-100%"
/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="0%"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="100%" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromXDelta="0"
android:toYDelta="100%" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
android:duration="500">
<scale
android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1"
android:toYScale="1"
android:pivotY="50%"
android:pivotX="50%"
>
</scale>
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/overshoot_interpolator">
<translate
android:duration="500"
android:fromXDelta="100%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%" />
<alpha
android:duration="500"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/overshoot_interpolator">
<translate
android:duration="500"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="100%"
android:toYDelta="0%" />
<alpha
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="200"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="100%"
android:pivotY="0%"
android:toXScale="1.2"
android:toYScale="1.2"></scale>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/auth_container"
app:navGraph="@navigation/nav_graph_auth"
app:defaultNavHost="true"
android:name="androidx.navigation.fragment.NavHostFragment"
tools:context=".AuthActivity">
</androidx.fragment.app.FragmentContainerView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph_main"
tools:context=".MainActivity"> tools:context=".MainActivity">
<Button </androidx.fragment.app.FragmentContainerView>
android:layout_width="wrap_content" \ No newline at end of file
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/button"
android:paddingHorizontal="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".ui.base.BaseFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".HomeFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".LoginFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".RegisterFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".VerificationFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/nav_graph_auth"
app:startDestination="@id/loginFragment">
<fragment
android:id="@+id/loginFragment"
android:name="uz.ssd.mobiuz.LoginFragment"
android:label="fragment_login"
tools:layout="@layout/fragment_login" />
<fragment
android:id="@+id/registerFragment"
android:name="uz.ssd.mobiuz.RegisterFragment"
android:label="fragment_register"
tools:layout="@layout/fragment_register" />
<fragment
android:id="@+id/verificationFragment"
android:name="uz.ssd.mobiuz.VerificationFragment"
android:label="fragment_verification"
tools:layout="@layout/fragment_verification" />
</navigation>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/nav_graph_main"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="uz.ssd.mobiuz.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" />
</navigation>
\ No newline at end of file
<resources> <resources>
<string name="app_name">MobiUz-Android</string> <string name="app_name">MobiUz-Android</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources> </resources>
\ No newline at end of file
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext{
hilt_jetpack_version = "1.0.0-alpha03"
hilt_version = "2.39.1"
live_data_version = "2.4.0"
nav_version = "2.3.5"
chuck_version = "1.1.0"
retrofit_version = "2.9.0"
}
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
...@@ -7,7 +15,8 @@ buildscript { ...@@ -7,7 +15,8 @@ buildscript {
dependencies { dependencies {
classpath "com.android.tools.build:gradle:7.0.3" classpath "com.android.tools.build:gradle:7.0.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.4.0-beta02"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment