Почему в приложении Kotlin Android я не могу больше отображать индикатор активности индикатора выполнения - PullRequest
0 голосов
/ 24 февраля 2020

У меня есть пользовательское действие, которое содержит индикатор активности индикатора выполнения, который виден во время доступа к сети, а затем становится невидимым после завершения доступа к сети. Затем индикатор активности снова становится видимым в начале другого доступа к сети и становится невидимым в конце его. Индикатор активности индикатора выполнения отображается дважды, как ожидалось, но между этими двумя событиями все еще остается относительно длительное время, когда пользователь ожидает и индикатор активности не отображается. Являются ли это лучшие места с точки зрения UX, чтобы иметь код индикатора активности индикатора выполнения во время выполнения какой-либо задачи?

Вот мой пользовательский класс активности с кодом индикатора активности индикатора выполнения:

package com.riverstonetech.gositeuk

import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.location.LocationManager
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Looper
import android.util.Log
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.app.ActionBar
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.google.android.gms.location.*
import com.google.firebase.firestore.FirebaseFirestore
import com.riverstonetech.gositeuk.Model.Site
import com.riverstonetech.gositeuk.Utilities.*
import kotlinx.android.synthetic.main.activity_county.*

class CountyActivity : AppCompatActivity() {

    // Access Cloud Firestore instance
    val db = FirebaseFirestore.getInstance()
    lateinit var fusedLocationProviderClient: FusedLocationProviderClient
    lateinit var locationRequest: LocationRequest
    lateinit var locationCallback: LocationCallback
    private var sites: ArrayList<Site> = ArrayList()
    private var siteDistances: ArrayList<Int> = ArrayList()
    private var recyclerView: RecyclerView? = null
    private var adapter: SiteAdapter? = null
    private var selectedCounty: String? = null
    val REQUEST_CODE = 1000

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_county)

        val window: Window = this.getWindow();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
        {
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.statusBarColor = Color.argb(255, 16, 128, 116)
        }

        selectedCounty = intent.getStringExtra("SUB_COUNTRY")!!

        // Custom action bar code to return to list of counties
        configureCustomActionBar()

        if (ActivityCompat.checkSelfPermission(
                this,
                android.Manifest.permission.ACCESS_FINE_LOCATION
            ) !=
            PackageManager.PERMISSION_GRANTED
        ) {

            Log.d("Debug", "Permission not granted")

            // Permission is not granted
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    android.Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Alert user to switch Location on in Settings
                val builder = AlertDialog.Builder(this)

                // Set the alert dialog title
                builder.setTitle("Permission needed")

                // Display a message on alert dialog
                builder.setMessage("Please grant permission for \"GoSiteUK\" to use your location")

                // Set a positive button and its click listener on alert dialog
                builder.setPositiveButton("OK") { dialog, which ->

                    startActivity(Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                        data = Uri.fromParts("package", packageName, null)
                    })
                }

                // Display a negative button on alert dialog
                builder.setNegativeButton("Cancel") { dialog, which ->
                    val intent = Intent(this, CountriesActivity::class.java)
                    startActivity(intent)

                }

                // Finally, make the alert dialog using builder
                val dialog: AlertDialog = builder.create()

                // Display the alert dialog on app interface
                dialog.show()


            } else {

                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
                    REQUEST_CODE
                )

                finish()

            }
        } else {

            // Permission has already been granted
            val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager

            if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) == false) {

                // Alert user to switch Location on in Settings
                val builder = AlertDialog.Builder(this)

                // Set the alert dialog title
                builder.setTitle("Turn on \"Location\"")

                // Display a message on alert dialog
                builder.setMessage("\"Location\" is currently turned off. Turn on \"Location\" to enable navigation function in \"GoSiteUK\"")

                // Set a positive button and its click listener on alert dialog
                builder.setPositiveButton("OK") { dialog, which ->

                    val intent = Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                    startActivity(intent)
                }

                // Display a negative button on alert dialog
                builder.setNegativeButton("Cancel") { dialog, which ->
                    val intent = Intent(this, CountriesActivity::class.java)
                    startActivity(intent)

                }

                // Finally, make the alert dialog using builder
                val dialog: AlertDialog = builder.create()

                // Display the alert dialog on app interface
                dialog.show()

            } else {

                sites.clear()

                var progressBar: ProgressBar = findViewById(R.id.countySitesProgressBar)

                progressBar.visibility = ProgressBar.VISIBLE

                db.collection("UKSites")
                    .document("England")
                    .collection("Counties")
                    .document(selectedCounty!!)
                    .collection(selectedCounty!!)
                    .get()
                    .addOnSuccessListener { documents ->

                        for (document in documents) {

                            val site = Site(document.data["Name"].toString())

                            site.address.line1 = document.data["Address Line 1"].toString()
                            site.address.line2 = document.data["Address Line 2"].toString()
                            site.address.line3 = document.data["Address Line 3"].toString()
                            site.address.line4 = document.data["Address Line 4"].toString()
                            site.address.postcode = document.data["Postcode"].toString()
                            site.address.phoneNumber = document.data["Telephone"].toString()
                            site.address.siteURL = document.data["Site URL"].toString()
                            site.description = document.data["Description"].toString()
                            site.price = document.data["Price"] as Double
                            site.distance = 0
                            site.locationCoordinate.Longitude = document.data["Longitude"] as Double
                            site.locationCoordinate.Latitude = document.data["Latitude"] as Double

                            sites.add(site)

                        }

                        progressBar.visibility = ProgressBar.GONE

                        BuildLocationRequest()

                        BuildLocationCallback()

                        // Create FusedProviderClient
                        fusedLocationProviderClient =
                            LocationServices.getFusedLocationProviderClient(this)

                        fusedLocationProviderClient.requestLocationUpdates(
                            locationRequest,
                            locationCallback,
                            Looper.myLooper()
                        )

                    }
                    .addOnFailureListener { exception ->
                        Log.e("Error", "Error getting documents: ", exception)
                    }

            }
        }
    }

    fun configureCustomActionBar() {

        val actionBar: ActionBar? = this.supportActionBar
        actionBar?.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM)
        actionBar?.setDisplayShowCustomEnabled(true)
        actionBar?.setCustomView(R.layout.sub_country_action_bar)

        val countyLabel: TextView = findViewById(R.id.subCountryTextView)
        countyLabel.text = selectedCounty

        val view: View? = actionBar?.customView
        actionBar?.setCustomView(view)

    }

    fun BuildLocationRequest() {
        locationRequest = LocationRequest()
        locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        locationRequest.interval = 5000
        locationRequest.fastestInterval = 3000
        locationRequest.smallestDisplacement = 10f

    }

    fun BuildLocationCallback() {
        locationCallback = object : LocationCallback() {

            override fun onLocationResult(p0: LocationResult?) {

                var progressBar: ProgressBar = findViewById(R.id.countySitesProgressBar)

                val currentCoordinate = p0!!.locations.get(p0.locations.size - 1)

                // Build URL for web request
                var distanceAPIURL: String = BASE_URL + "&origins="
                var siteLatitude: Double
                var siteLongitude: Double

                // add current location parameter to API URL
                progressBar.visibility = ProgressBar.VISIBLE
                distanceAPIURL += "${currentCoordinate.latitude},${currentCoordinate.longitude}"

                // add site destinations to API URL
                distanceAPIURL += "&destinations="

                // Build API request from site locations
                for (site in sites) {

                    siteLatitude = site.locationCoordinate.Latitude!!
                    siteLongitude = site.locationCoordinate.Longitude!!

                    if (site == sites.first()) {

                        distanceAPIURL += "${siteLatitude}%2C${siteLongitude}"

                    } else {

                        distanceAPIURL += "%7C${siteLatitude}%2C${siteLongitude}"

                    }

                }

                // Add API KEY
                distanceAPIURL += GOOGLE_API_KEY

                // Make web requests to Google
                val distanceRequest = object :
                    StringRequest(Method.POST, distanceAPIURL, Response.Listener { response ->


                        // Parse out distances from returned data
                        siteDistances = parseOutDistanceValues(response)

                        // Update distance information for each site
                        for (siteIndex in 0 until sites.size) {

                            sites[siteIndex].distance = siteDistances[siteIndex]

                        }

                        // Sort sites in ascending order of distance
                        sites = sortByDistance(sites)

                        // Recycler View code here
                        recyclerView = findViewById<View>(R.id.countySitesRecyclerView) as RecyclerView

                        adapter = SiteAdapter(this@CountyActivity, sites)

                        val layoutManager = LinearLayoutManager(applicationContext)

                        recyclerView!!.layoutManager = layoutManager

                        recyclerView!!.itemAnimator = DefaultItemAnimator()

                        // Add a neat dividing line between items in the list
                        recyclerView!!.addItemDecoration(
                            DividerItemDecoration(
                                this@CountyActivity,
                                LinearLayoutManager.VERTICAL
                            )
                        )

                        recyclerView!!.addItemDecoration(
                            ItemOffsetDecoration(
                                applicationContext,
                                0,
                                0
                            )
                        )

                        // set the adapter
                        recyclerView!!.adapter = adapter

                        progressBar.visibility = ProgressBar.GONE


                    }, Response.ErrorListener { error ->

                        Log.d(
                            "ERROR",
                            "Could not calculate distances to sites: ${error.localizedMessage}"
                        )

                    }) {

                }

                Volley.newRequestQueue(applicationContext).add(distanceRequest)

            }
        }
    }

    fun previousSubCountryListButtonClicked(view: View) {

        val intent: Intent = Intent(this, CountriesActivity::class.java)
        startActivity(intent)

    }
}

1 Ответ

0 голосов
/ 24 февраля 2020

Я бы предложил вам несколько модификаций.

  1. Объявите индикатор выполнения как участник вашей деятельности и инициализируйте его (var progressBar: ProgressBar = findViewById (R.id.countySitesProgressBar)) из onCreate
  2. В вашем макете всегда показывайте его по умолчанию. Единственное место, где вам нужно это скрыть, - это когда вы отправляете / получаете ответ от своего веб-сервиса (из того, что я видел, вы получаете местоположение, а затем что-то делаете с ним и передаете в веб-сервис.
  3. (необязательно) Я бы порекомендовал вам использовать кинжал или шаблоны проектирования (например, mvp / mvvm) для более эффективного повторного использования и инкапсуляции вашего кода. Если вам потребуется включить больше функций в свою деятельность, впоследствии будет сложно отладить ее.

Редактировать

Если вы также хотите включить просмотр текста как часть экрана загрузки, вы можете попробовать что-то вроде этого:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize">

            <TextView
                android:id="@+id/tvToolbarTitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:textAllCaps="true"
                android:textColor="@color/white"
                android:textSize="@dimen/text_20"
                android:textStyle="bold" />

        </androidx.appcompat.widget.Toolbar>
    </com.google.android.material.appbar.AppBarLayout>


    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/appbar"
        app:layout_constraintStart_toStartOf="parent"
        >

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/loading_layout"
            android:visibility="gone"> <--------

            <ProgressBar
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                android:id="@+id/horizontal_progressbar_indeterminate"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:indeterminate="true"
                app:layout_constraintLeft_toLeftOf="parent" />

            <TextView
                android:id="@+id/user_message"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_constraintTop_toTopOf="parent"
                android:gravity="center"
                android:textSize="20dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                tools:text="Fetching Location / Fetching Data..."/>

        </androidx.constraintlayout.widget.ConstraintLayout>

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/content1">

            <TextView
                tools:text="Can be recyclerview with some data"
                android:layout_width="match_parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                android:gravity="center"
                android:textSize="20sp"
                android:layout_height="match_parent"/>

        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

Основное изменение заключается в том, что индикатор выполнения с текстом находится в отдельном макете, а не является частью вашего контента. Вместо изменения видимости индикатора выполнения вам нужно изменить видимость загрузочного макета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...