diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6f519f4..b9190a4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,7 @@ + @@ -39,11 +41,13 @@ diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..2d21e27 Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/com/example/fieldagent/data/apis/WebService.kt b/app/src/main/java/com/example/fieldagent/data/apis/WebService.kt index 952e163..0245813 100644 --- a/app/src/main/java/com/example/fieldagent/data/apis/WebService.kt +++ b/app/src/main/java/com/example/fieldagent/data/apis/WebService.kt @@ -15,13 +15,12 @@ interface WebService { private const val INSPECTIONS = "inspections" private const val DAMAGES = "damages" private const val RESTROOM_LIST = "restroom-conditions" - private const val ITEM_LIST = "combined-list" private const val CATEGORY = "categories" private const val SELECT_CATEGORY = "categories" - private const val SUB_CATEGORY = "subcategories" private const val USER = "users" + } /*POST APIS*/ diff --git a/app/src/main/java/com/example/fieldagent/data/models/responses/InspectionData.kt b/app/src/main/java/com/example/fieldagent/data/models/responses/InspectionData.kt index f315b79..0f729ad 100644 --- a/app/src/main/java/com/example/fieldagent/data/models/responses/InspectionData.kt +++ b/app/src/main/java/com/example/fieldagent/data/models/responses/InspectionData.kt @@ -29,6 +29,9 @@ data class InspectionList ( val totalRestrooms: Long? = null, val restroomCondition: String? = null, val vat: String? = null, + + @SerializedName("unique_hash") + val uniqueHash: String? = null, val image: String? = null, val isCompleted: Boolean? = null, val isDeleted: Boolean? = null, diff --git a/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteFragment.kt b/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteFragment.kt index 00814b7..1bfd694 100644 --- a/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteFragment.kt +++ b/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteFragment.kt @@ -8,6 +8,8 @@ import android.content.pm.PackageManager import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.location.Geocoder +import android.location.Location +import android.location.LocationRequest import android.net.Uri import android.os.Build import android.os.Bundle @@ -53,11 +55,16 @@ import com.example.fieldagent.utils.gone import com.example.fieldagent.utils.hideKeyboard import com.example.fieldagent.utils.hideShowView import com.example.fieldagent.utils.isConnectedToInternet +import com.example.fieldagent.utils.showFullScreenImage import com.example.fieldagent.utils.showSnackBar import com.example.fieldagent.utils.uriToFile import com.example.fieldagent.utils.visible import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationCallback +import com.google.android.gms.location.LocationResult import com.google.android.gms.location.LocationServices +import com.google.android.gms.location.Priority +import com.google.android.gms.tasks.CancellationTokenSource import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -228,6 +235,10 @@ class AddSiteFragment : Fragment() { binding.ivCloseImage.gone() imageUri=null; } + binding.ivSetImage.setOnClickListener { + + showFullScreenImage(imageUri.toString(),requireActivity()) + } // Permission launcher permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> @@ -279,6 +290,9 @@ class AddSiteFragment : Fragment() { binding.etSupervisorContact.text.toString().isEmpty() -> { binding.etSupervisorContact.showSnackBar(getString(R.string.please_enter_supervisor_contact_number)) } + binding.etSupervisorContact.text.toString().length < 7 || binding.etSupervisorContact.text.toString().length > 11 -> { + binding.etSupervisorContact.showSnackBar(getString(R.string.contact_number_length_error)) + } binding.etSupervisorAuthority.text.toString().isEmpty() -> { binding.etSupervisorAuthority.showSnackBar(getString(R.string.please_enter_supervisor_authority_mosque)) @@ -331,7 +345,7 @@ class AddSiteFragment : Fragment() { it ?: return@Observer when (it.status) { Status.SUCCESS -> { - + parentFragmentManager.setFragmentResult("refresh_home", Bundle()) findNavController().popBackStack(); progressDialog.setLoading(false) } @@ -386,12 +400,32 @@ class AddSiteFragment : Fragment() { @SuppressLint("MissingPermission") private fun getCurrentLocation() { - fusedLocationClient.lastLocation.addOnSuccessListener { location -> + val locationRequest = LocationRequest.Builder( + Priority.PRIORITY_HIGH_ACCURACY, + 5000 // interval in milliseconds + ).build() + fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null) + /* fusedLocationClient.lastLocation.addOnSuccessListener { location -> if (location != null) { getAddressFromLocation(location.latitude, location.longitude) } else { Toast.makeText(requireActivity(), getString(R.string.could_not_fetch_location), Toast.LENGTH_SHORT).show() } + }*/ + } + + // Stop location updates + private fun stopLocationUpdates() { + fusedLocationClient.removeLocationUpdates(locationCallback) + } + + private val locationCallback = object : LocationCallback() { + override fun onLocationResult(locationResult: LocationResult) { + super.onLocationResult(locationResult) + // Process the location data + val location: Location = locationResult.lastLocation!! + Log.e("ChecLofgggf==>","${location.longitude}") + // ... (Display location on map, etc.) ... } } diff --git a/app/src/main/java/com/example/fieldagent/ui/damagedetails/DamageDetailsFragment.kt b/app/src/main/java/com/example/fieldagent/ui/damagedetails/DamageDetailsFragment.kt index 69e68e5..7512863 100644 --- a/app/src/main/java/com/example/fieldagent/ui/damagedetails/DamageDetailsFragment.kt +++ b/app/src/main/java/com/example/fieldagent/ui/damagedetails/DamageDetailsFragment.kt @@ -409,7 +409,9 @@ class DamageDetailsFragment : Fragment() { val tempData=it.data?.data if(tempData?.categories!=null && tempData.categories.isNotEmpty() && tempData.categories[0].subCategories!=null && tempData.categories[0].subCategories!!.isNotEmpty()) { - tempData.categories[0].subCategories?.let { it1 -> subCategoryList.addAll(it1) } + tempData.categories[0].subCategories?.let { it1 -> + subCategoryList.clear() + subCategoryList.addAll(it1) } binding.llUnits.visible() binding.llSubItem.visible() val subCategoryNames = subCategoryList.map { it.name } diff --git a/app/src/main/java/com/example/fieldagent/ui/damagedetails/adapter/DamageDetailsAdapter.kt b/app/src/main/java/com/example/fieldagent/ui/damagedetails/adapter/DamageDetailsAdapter.kt index 25178b6..7964c1c 100644 --- a/app/src/main/java/com/example/fieldagent/ui/damagedetails/adapter/DamageDetailsAdapter.kt +++ b/app/src/main/java/com/example/fieldagent/ui/damagedetails/adapter/DamageDetailsAdapter.kt @@ -11,6 +11,8 @@ import com.example.fieldagent.ui.damagedetails.DamageDetailsFragment import com.example.fieldagent.utils.gone import com.example.fieldagent.utils.visible import androidx.core.net.toUri +import com.example.fieldagent.utils.IMAGE_BASE_URL +import com.example.fieldagent.utils.showFullScreenImage class DamageDetailsAdapter( @@ -57,6 +59,10 @@ class DamageDetailsAdapter( holder.binding.ivCloseImage.setOnClickListener { damageDetailsFragment.removeImage(position) } + + holder.binding.cardImage.setOnClickListener { + showFullScreenImage(imageList[position].toString(),holder.binding.root.context) + } } else { holder.binding.rlUploadImage.visible() holder.binding.cardImage.gone() diff --git a/app/src/main/java/com/example/fieldagent/ui/damagelist/DamageListFragment.kt b/app/src/main/java/com/example/fieldagent/ui/damagelist/DamageListFragment.kt index 06b3e5f..5f50fb9 100644 --- a/app/src/main/java/com/example/fieldagent/ui/damagelist/DamageListFragment.kt +++ b/app/src/main/java/com/example/fieldagent/ui/damagelist/DamageListFragment.kt @@ -1,15 +1,19 @@ package com.example.fieldagent.ui.damagelist +import android.app.DownloadManager import android.content.ContentValues +import android.content.Context import android.content.res.Resources import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.pdf.PdfDocument +import android.net.Uri import android.os.Bundle import android.os.Environment import android.provider.MediaStore +import android.util.Log import android.view.Gravity import androidx.fragment.app.Fragment import android.view.LayoutInflater @@ -42,6 +46,25 @@ import javax.inject.Inject import androidx.core.graphics.toColorInt import androidx.core.graphics.createBitmap import androidx.core.text.layoutDirection +import com.example.fieldagent.utils.DOWNLOAD_URL +import okhttp3.OkHttpClient + + +import java.io.IOException + +import okhttp3.ResponseBody +import retrofit2.Retrofit + +import retrofit2.* +import retrofit2.converter.gson.GsonConverterFactory + +import retrofit2.http.GET +import retrofit2.http.Streaming +import retrofit2.http.Url +import java.io.* +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response @AndroidEntryPoint @@ -63,6 +86,7 @@ class DamageListFragment : Fragment() { private var inspectionId="" private var clickDeletePos=-1 private var vatValue="" + private var hashCode="" override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -118,8 +142,12 @@ class DamageListFragment : Fragment() { binding.btnExportPdf.gone() }else{ vatValue=tempList[0].vat.toString() + hashCode=tempList[0].uniqueHash.toString() + Log.e("Checkkkschhsh==>","${hashCode}") binding.clNoData.gone() binding.btnExportPdf.visible() + + } tempList[0].damages?.let { it1 -> adapter.submitList(it1) @@ -197,6 +225,18 @@ class DamageListFragment : Fragment() { binding.btnExportPdf.setOnClickListener { // setUpPdf() + + val url = DOWNLOAD_URL+hashCode + val downloadsFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + val fileName = url.substringAfterLast('/')+".pdf" + val destinationFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName) + Log.e("cHehfehchh===>","${url}"); + val success = downloadPdfFile(url, destinationFile) + /* if (success) { + Toast.makeText(context, getString(R.string.pdf_saved), Toast.LENGTH_LONG).show() + } else { + Toast.makeText(context, getString(R.string.pdf_failed), Toast.LENGTH_LONG).show() + }*/ } } @@ -562,8 +602,97 @@ class DamageListFragment : Fragment() { } + + + fun downloadPdfFile(fileUrl: String, outputFile: File) { + + val okHttpClient = OkHttpClient.Builder() + .followRedirects(true) + .followSslRedirects(true) + .build() + + val retrofit = Retrofit.Builder() + .baseUrl("https://example.com/") // Placeholder, overridden by @Url + .client(okHttpClient) + .addConverterFactory(GsonConverterFactory.create()) + .build() + + val service = retrofit.create(FileDownloadService::class.java) + val call = service.downloadFile(fileUrl) + + call.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (!response.isSuccessful) { + println("❌ Server returned error: ${response.code()}") + return + } + + val contentType = response.body()?.contentType()?.toString() + val contentLength = response.body()?.contentLength() ?: 0L + + println("✅ Content-Type: $contentType") + println("✅ Content-Length: $contentLength bytes") + + if (contentType?.contains("pdf", ignoreCase = true) == true) { + response.body()?.let { body -> + val success = saveFile(body, outputFile) + if (success) { + println("✅ PDF saved at: ${outputFile.absolutePath}") + } else { + println("❌ Failed to save PDF.") + } + } + } else { + println("❌ The file is not a PDF (Content-Type: $contentType).") + } + } + + override fun onFailure(call: Call, t: Throwable) { + println("❌ Download error: ${t.localizedMessage}") + } + }) + } + + fun saveFile(body: ResponseBody, outputFile: File): Boolean { + return try { + val inputStream = body.byteStream() + val outputStream = FileOutputStream(outputFile) + val buffer = ByteArray(4096) + var bytesRead: Int + + while (inputStream.read(buffer).also { bytesRead = it } != -1) { + outputStream.write(buffer, 0, bytesRead) + } + + outputStream.flush() + outputStream.close() + inputStream.close() + + // Verify PDF file header + val header = FileInputStream(outputFile).use { it.readNBytes(4) } + if (String(header) != "%PDF") { + outputFile.delete() + println("❌ Invalid PDF signature in downloaded file.") + false + } else { + true + } + } catch (e: IOException) { + e.printStackTrace() + false + } + } + + override fun onDestroyView() { super.onDestroyView() _binding = null } -} \ No newline at end of file +} + +interface FileDownloadService { + @Streaming + @GET + fun downloadFile(@Url fileUrl: String): Call +} + diff --git a/app/src/main/java/com/example/fieldagent/ui/damagelist/adapter/DamageListAdapter.kt b/app/src/main/java/com/example/fieldagent/ui/damagelist/adapter/DamageListAdapter.kt index 9ff19cf..97cfc9e 100644 --- a/app/src/main/java/com/example/fieldagent/ui/damagelist/adapter/DamageListAdapter.kt +++ b/app/src/main/java/com/example/fieldagent/ui/damagelist/adapter/DamageListAdapter.kt @@ -51,6 +51,7 @@ class DamageListAdapter(val damageListFragment: DamageListFragment) : RecyclerVi } + } fun submitList(list: ArrayList) { diff --git a/app/src/main/java/com/example/fieldagent/ui/damagelist/adapter/ShowImageAdapter.kt b/app/src/main/java/com/example/fieldagent/ui/damagelist/adapter/ShowImageAdapter.kt index 9565a09..32d9c0e 100644 --- a/app/src/main/java/com/example/fieldagent/ui/damagelist/adapter/ShowImageAdapter.kt +++ b/app/src/main/java/com/example/fieldagent/ui/damagelist/adapter/ShowImageAdapter.kt @@ -10,6 +10,7 @@ import com.example.fieldagent.databinding.FillImageAdapterBinding import com.example.fieldagent.ui.homescreen.adapter.HomeAdapter.ViewHolder import com.example.fieldagent.utils.DateUtils.getTimeAgo import com.example.fieldagent.utils.IMAGE_BASE_URL +import com.example.fieldagent.utils.showFullScreenImage class ShowImageAdapter(private val images: List?) : RecyclerView.Adapter() { @@ -24,6 +25,10 @@ class ShowImageAdapter(private val images: List?) : RecyclerView.Adapter .into(binding.ivUploadImage) + binding.rvImage.setOnClickListener { + + showFullScreenImage(IMAGE_BASE_URL + imageUrl,binding.root.context) + } } } diff --git a/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeFragment.kt b/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeFragment.kt index c97e7d6..c5d4b69 100644 --- a/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeFragment.kt +++ b/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeFragment.kt @@ -117,11 +117,21 @@ class HomeFragment : Fragment() { prefsManager.save(IS_LOGIN,true) - if (isFirstPage) { + if (viewModel.inspections.value?.data?.data?.inspections.isNullOrEmpty()) { val hashMap = HashMap() hashMap[LIMIT_TEXT] = PER_PAGE_LOAD hashMap[PAGE_TEXT] = PER_PAGE viewModel.getInspectionList(hashMap); + + } + + parentFragmentManager.setFragmentResultListener("refresh_home", viewLifecycleOwner) { _, _ -> + refreshPagination() + val hashMap = HashMap() + hashMap[LIMIT_TEXT] = PER_PAGE_LOAD + hashMap[PAGE_TEXT] = PER_PAGE + viewModel.getInspectionList(hashMap) + binding.rvList.scrollToPosition(0) } @@ -318,6 +328,8 @@ class HomeFragment : Fragment() { items.clear() // Clear the list on first load to prevent duplicates items.addAll(tempList) adapter.notifyDataSetChanged() + + } else { val oldSize = items.size // Add only new items to avoid duplication diff --git a/app/src/main/java/com/example/fieldagent/ui/homescreen/adapter/HomeAdapter.kt b/app/src/main/java/com/example/fieldagent/ui/homescreen/adapter/HomeAdapter.kt index 96ecd8f..416ca40 100644 --- a/app/src/main/java/com/example/fieldagent/ui/homescreen/adapter/HomeAdapter.kt +++ b/app/src/main/java/com/example/fieldagent/ui/homescreen/adapter/HomeAdapter.kt @@ -25,6 +25,7 @@ import com.example.fieldagent.utils.DateUtils.getTimeAgo import com.example.fieldagent.utils.IMAGE_BASE_URL import com.example.fieldagent.utils.LoadingStatus.ITEM import com.example.fieldagent.utils.LoadingStatus.LOADING +import com.example.fieldagent.utils.showFullScreenImage class HomeAdapter(private val fragment: HomeFragment,private val items: ArrayList) : RecyclerView.Adapter() { @@ -76,6 +77,12 @@ class HomeAdapter(private val fragment: HomeFragment,private val items: ArrayLi .error(R.drawable.home_item) // Set a default image if the requested image fails to load .fallback(R.drawable.home_item) .into(binding.ivImage) + + + binding.ivImage.setOnClickListener { + showFullScreenImage(IMAGE_BASE_URL+item.image,binding.root.context) + } + } } diff --git a/app/src/main/java/com/example/fieldagent/utils/AppConstant.kt b/app/src/main/java/com/example/fieldagent/utils/AppConstant.kt index 60cc0a1..baff96b 100644 --- a/app/src/main/java/com/example/fieldagent/utils/AppConstant.kt +++ b/app/src/main/java/com/example/fieldagent/utils/AppConstant.kt @@ -14,6 +14,7 @@ const val SEARCH = "search" const val PAGE_TEXT = "page" const val PER_PAGE_LOAD = "10" const val IMAGE_BASE_URL = "https://field-api.dmlabs.in/api/image/" +const val DOWNLOAD_URL = "https://field-admin.dmlabs.in/inspections/report/" diff --git a/app/src/main/java/com/example/fieldagent/utils/ConnectionDetector.kt b/app/src/main/java/com/example/fieldagent/utils/ConnectionDetector.kt index d18eaf9..9adf927 100644 --- a/app/src/main/java/com/example/fieldagent/utils/ConnectionDetector.kt +++ b/app/src/main/java/com/example/fieldagent/utils/ConnectionDetector.kt @@ -20,6 +20,21 @@ import com.example.fieldagent.R fun isConnectedToInternet(context: Context, showAlert: Boolean): Boolean { val isConnected = isConnectedToInternet(context) + if (!isConnected) + { + if(showAlert) + { + Toast.makeText(context,context.getString(R.string.check_internet),Toast.LENGTH_SHORT).show() + } + + return false + }else{ + return true + } +} +fun isConnectedToInternetHome(context: Context, showAlert: Boolean): Boolean { + val isConnected = isConnectedToInternet(context) + if (!isConnected) { Toast.makeText(context,context.getString(R.string.check_internet),Toast.LENGTH_SHORT).show() diff --git a/app/src/main/java/com/example/fieldagent/utils/GeneralFunction.kt b/app/src/main/java/com/example/fieldagent/utils/GeneralFunction.kt index 4b443fa..a239a8f 100644 --- a/app/src/main/java/com/example/fieldagent/utils/GeneralFunction.kt +++ b/app/src/main/java/com/example/fieldagent/utils/GeneralFunction.kt @@ -1,5 +1,6 @@ package com.example.fieldagent.utils +import android.app.AlertDialog import android.app.Dialog import android.content.Context import android.graphics.Color @@ -7,6 +8,7 @@ import android.graphics.drawable.ColorDrawable import android.net.Uri import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup import android.view.Window import android.view.inputmethod.InputMethodManager import android.widget.TextView @@ -21,6 +23,9 @@ import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody import java.io.File import androidx.core.net.toUri +import com.bumptech.glide.Glide +import com.example.fieldagent.databinding.DialogFullScreenImageBinding +import androidx.core.graphics.drawable.toDrawable fun View.gone() { @@ -139,6 +144,38 @@ fun Context.showUpdateDialog( dialog.show() } +fun showFullScreenImage(imagePath: String, context: Context) { + + val dialogBinding = DialogFullScreenImageBinding.inflate(LayoutInflater.from(context)) + + val dialog = AlertDialog.Builder(context, R.style.TransparentDialog) + .setView(dialogBinding.root) + .create() + + val isUrl = imagePath.startsWith("http://") || imagePath.startsWith("https://") + + if (isUrl) { + Glide.with(context) + .load(imagePath) + .into(dialogBinding.fullscreenImage) + } else { + Glide.with(context) + .load(imagePath.toUri()) + .into(dialogBinding.fullscreenImage) + } + dialogBinding.closeButton.setOnClickListener { dialog.dismiss() } + + dialog.show() + + + dialog.window?.setLayout( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + dialog.window?.setBackgroundDrawable(Color.TRANSPARENT.toDrawable()) +} + + fun hideKeyboard(fragment: Fragment) { val inputMethodManager = fragment.requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager diff --git a/app/src/main/res/layout/damage_image_adapter.xml b/app/src/main/res/layout/damage_image_adapter.xml index 16cc78d..80c4b88 100644 --- a/app/src/main/res/layout/damage_image_adapter.xml +++ b/app/src/main/res/layout/damage_image_adapter.xml @@ -6,11 +6,13 @@ android:layout_height="@dimen/dp_100" android:layout_marginTop="@dimen/dp_4" android:layout_marginEnd="@dimen/dp_16" - android:background="@drawable/line_spce_line"> + > + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fill_image_adapter.xml b/app/src/main/res/layout/fill_image_adapter.xml index b16f2ed..12104de 100644 --- a/app/src/main/res/layout/fill_image_adapter.xml +++ b/app/src/main/res/layout/fill_image_adapter.xml @@ -7,6 +7,7 @@ android:layout_marginTop="@dimen/dp_4" android:layout_marginEnd="@dimen/dp_16" android:elevation="0dp" + android:layout_marginStart="@dimen/dp_8" app:cardCornerRadius="@dimen/dp_6" android:layout_margin="@dimen/dp_2" android:background="@drawable/line_space_line_color"> diff --git a/app/src/main/res/layout/fragment_add_site.xml b/app/src/main/res/layout/fragment_add_site.xml index d3d081a..6361e80 100644 --- a/app/src/main/res/layout/fragment_add_site.xml +++ b/app/src/main/res/layout/fragment_add_site.xml @@ -178,7 +178,7 @@ android:hint="@string/please_enter_supervisor_contact_number" android:maxLines="1" android:inputType="number" - android:maxLength="15" + android:maxLength="11" android:singleLine="true" android:ellipsize="end" android:fontFamily="@font/montserratregular" @@ -448,7 +448,7 @@ app:layout_constraintEnd_toStartOf="@id/rightGuide" app:layout_constraintTop_toBottomOf="@id/txtAddImage" android:layout_marginTop="@dimen/dp_4" - android:background="@drawable/line_spce_line" + android:layout_marginBottom="@dimen/dp_20" > @@ -471,6 +471,7 @@ android:visibility="gone" app:cardCornerRadius="@dimen/dp_4" android:elevation="0dp" + android:layout_margin="@dimen/dp_1" > - - - - - - - - - - - - - - - - - - - - - - + + android:background="@color/white"> - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - android:textSize="@dimen/sp_12" + + + + + + + + + + + - - + + - + - + + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="*" + android:fontFamily="@font/montserratregular" + android:textColor="@color/star_color" + android:textSize="@dimen/sp_14" + /> - + + + +