Home > Back-end >  Why androidx.appcompat.widget.AppCompatEditText cannot be cast to com.google.android.material.textfi
Why androidx.appcompat.widget.AppCompatEditText cannot be cast to com.google.android.material.textfi

Time:08-10

I would like to be able to create a path between two points by entering coordinates through two text fields and use the function I created, to create the path, using a button that takes the two coordinates entered as the end point.

when i try to insert the reference to the two text fields i have this error, how can i solve it?

my code is this below:


package uk.co.lorenzopulcinelli.trackapp

import android.Manifest
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.os.StrictMode
import android.util.DisplayMetrics
import android.util.Log
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.res.ResourcesCompat
import androidx.preference.PreferenceManager
import com.google.android.material.textfield.TextInputEditText
import org.osmdroid.api.IMapController
import org.osmdroid.bonuspack.clustering.RadiusMarkerClusterer
import org.osmdroid.bonuspack.location.NominatimPOIProvider
import org.osmdroid.bonuspack.location.POI
import org.osmdroid.bonuspack.routing.OSRMRoadManager
import org.osmdroid.bonuspack.routing.Road
import org.osmdroid.bonuspack.routing.RoadManager
import org.osmdroid.bonuspack.routing.RoadNode
import org.osmdroid.bonuspack.utils.BonusPackHelper
import org.osmdroid.config.Configuration
import org.osmdroid.config.Configuration.*
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.CustomZoomButtonsController
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.compass.CompassOverlay
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider
import org.osmdroid.views.overlay.*
import org.osmdroid.views.overlay.gestures.RotationGestureOverlay
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay
import org.osmdroid.views.overlay.Marker

class MainActivity : AppCompatActivity() {
    private lateinit var mapView : MapView
    private lateinit var myLocationNewOverlay: MyLocationNewOverlay
    private lateinit var compassOverlay: CompassOverlay
    private lateinit var mapController: IMapController
    private lateinit var road: Road
    private lateinit var editTextLatitudine: TextInputEditText
    private lateinit var editTextLongitudine: TextInputEditText

    override fun onCreate(savedInstanceState: Bundle?) {
        // disabilita la policy di strictMode nella onCreate per non fare chiamate network in async tasks
        val policy: StrictMode.ThreadPolicy = StrictMode.ThreadPolicy.Builder().permitAll().build()
        StrictMode.setThreadPolicy(policy)

        super.onCreate(savedInstanceState)

        //richiesta per gestire i permessi
        requestPermission()


        // inizializza la configurazione di osmdroid, non funziona se non si importa org.osmdroid.config.Configuration.*
        getInstance().load(this, PreferenceManager.getDefaultSharedPreferences(this))

        //crea la mappa
        setContentView(R.layout.activity_main)
        mapView = findViewById<MapView>(R.id.map)
        mapView.setTileSource(TileSourceFactory.MAPNIK)
        mapView.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)

        // crea MapController e setta posizione iniziale
        mapController = mapView.controller
        // crea overlay posizione
        myLocationNewOverlay = MyLocationNewOverlay(GpsMyLocationProvider(this), mapView)
        myLocationNewOverlay.enableMyLocation()
        myLocationNewOverlay.enableMyLocation()
        myLocationNewOverlay.isDrawAccuracyEnabled = true
        myLocationNewOverlay.runOnFirstFix { runOnUiThread {
            mapController.animateTo(myLocationNewOverlay.myLocation)
            mapController.setZoom(9.0)
            }
        }
        mapView.overlays.add(myLocationNewOverlay)

        //set user agent
        Configuration.getInstance().userAgentValue = "lolloMaps"

        // controllo
        println(myLocationNewOverlay.myLocation)
        println("creato")

        // attiva bussola, Non Funziona!
        compassOverlay = CompassOverlay(this, InternalCompassOrientationProvider(this), mapView)
        compassOverlay.enableCompass()
        mapView.overlays.add(compassOverlay)

        // attivare griglia latitudine e longitudine
        // val overlay = LatLonGridlineOverlay2()
        // mapView.overlays.add(overlay)

        // abilita gesture rotazione e zoom
        val rotationGestureOverlay = RotationGestureOverlay(mapView)
        rotationGestureOverlay.isEnabled
        mapView.setMultiTouchControls(true)
        mapView.overlays.add(rotationGestureOverlay)

        // abilita mia posizione
        myLocationNewOverlay = MyLocationNewOverlay(GpsMyLocationProvider(this), mapView)
        myLocationNewOverlay.enableMyLocation()
        mapView.overlays.add(myLocationNewOverlay)

        // abilita overlay scala
        val dm : DisplayMetrics = resources.displayMetrics
        val scaleBarOverlay = ScaleBarOverlay(mapView)
        scaleBarOverlay.setCentred(true)
        scaleBarOverlay.setScaleBarOffset(dm.widthPixels / 2, 10)
        mapView.overlays.add(scaleBarOverlay)

        val mapEventsReceiver: MapEventsReceiverImpl = MapEventsReceiverImpl()
        val mapEventsOverlay: MapEventsOverlay = MapEventsOverlay(mapEventsReceiver)
        mapView.overlays.add(mapEventsOverlay)

        // traccia percorso tra i punti degli editText
        editTextLatitudine = findViewById<TextInputEditText>(R.id.editTextLatitudine)
        editTextLongitudine = findViewById<TextInputEditText>(R.id.editTextLongitudine)


        val b = findViewById<Button>(R.id.location)
        b.setOnClickListener{
            Log.d("Percorso", "Premuto")
            val lalati: Double = editTextLatitudine.text.toString().toDouble()
            val lolong: Double = editTextLongitudine.text.toString().toDouble()
            println("latitudine: $lolong, longitudine: $lalati")
            routePath(22.22, 44.33, lolong, lalati)
        }

        // traccia percorso tra due punti
        routePath(43.12628, 12.04705, 43.12124, 11.97211)

        // inserisce POIs nella mappa
        val startPoint1:GeoPoint = GeoPoint(43.12628, 12.04705)
        val poiProvider: NominatimPOIProvider = NominatimPOIProvider("OSMBonusPackTutoUserAgent")
        val pois: ArrayList<POI> = poiProvider.getPOICloseTo(startPoint1, "fuel", 50, 0.1)
        val poisRoad: ArrayList<POI> = poiProvider.getPOIAlong(road.routeLow, "cinema", 50, 0.1)

        val poiMarkers: FolderOverlay = FolderOverlay()
        mapView.overlays.add(poiMarkers)

        val poiIcon: Drawable? = ResourcesCompat.getDrawable(resources, R.drawable.marker_poi_default, null)
        for (poi: POI in pois){
            val poiMarker: Marker = Marker(mapView)
            poiMarker.title = poi.mType
            poiMarker.snippet = poi.mDescription
            poiMarker.position = poi.mLocation
            poiMarker.icon = poiIcon
            /*if (poi.mThumbnail != null){
                poiItem.setImage(BitmapDrawable(poi.mThumbnail))
            }*/
            poiMarkers.add(poiMarker)
            mapView.invalidate()
        }

        for (poi: POI in poisRoad){
            val rPoiMarker: Marker = Marker(mapView)
            rPoiMarker.title = poi.mType
            rPoiMarker.snippet = poi.mDescription
            rPoiMarker.position = poi.mLocation
            rPoiMarker.icon = poiIcon
            /*if (poi.mThumbnail != null){
                poiItem.setImage(BitmapDrawable(poi.mThumbnail))
            }*/
            poiMarkers.add(rPoiMarker)
            mapView.invalidate()
        }

        // clustering markers
        val radiusMarkerCluster: RadiusMarkerClusterer = RadiusMarkerClusterer(this)
        val clusterIcon: Bitmap = BonusPackHelper.getBitmapFromVectorDrawable(this, R.drawable.marker_cluster)
        radiusMarkerCluster.setIcon(clusterIcon)


    }

    override fun onResume() {
        super.onResume()
        mapView.onResume()
    }

    override fun onPause() {
        super.onPause()
        mapView.onPause()
    }

    //funzione per controllare se ho i permessi
    private fun hasPermission() : Boolean {
        // ritorna true quando abbiamo i permessi
        return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
    }


    //funzione per richiedere i permessi
    private fun requestPermission() {
        //aggiungo i permessi ad una lista
        val permission = mutableListOf<String>()
        // se non ho i permessi
        if (!hasPermission()) {
            // aggiungo i permesi alla lista
            permission.add(Manifest.permission.ACCESS_FINE_LOCATION)
        }
        // concede i permessi nella lista
        if (permission.isNotEmpty()) {
            ActivityCompat.requestPermissions(this, permission.toTypedArray(), 0)
        }
    }

    // funzione per aggiungere Marker
    private fun mioMarker(lati: Double, longi: Double, i: Int) {
        val pinMarker = Marker(mapView)
        val geoPoint = GeoPoint(lati, longi)
        pinMarker.position = geoPoint
        pinMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
        pinMarker.title = "Title"
        pinMarker.subDescription = "io sono il pin #$i con coordinate $lati, $longi."
        pinMarker.isDraggable = true
        mapView.overlays.add(pinMarker)
        mapView.invalidate()
    }

    // funzione per creare percorso fra due punti
    private fun routePath(p1Latit: Double, p1Laong: Double, p2Latit: Double, p2Laong: Double){
        println("inizio")
        val roadManager:RoadManager = OSRMRoadManager(this, "lolloMaps")
        OSRMRoadManager.MEAN_BY_FOOT
        println("passo1 - creoArrayList")
        val waypoints = arrayListOf<GeoPoint>()
        println("passo2 - CreoPuntiEAggiungoInArrayList")
        val startPoint: GeoPoint = GeoPoint(p1Latit, p1Laong) //43.12628, 12.04705
        waypoints.add(startPoint)
        val endPoint: GeoPoint = GeoPoint(p2Latit, p2Laong) //43.12124, 11.97211
        waypoints.add(endPoint)
        println("passo3 - CreoStrada")
        road = roadManager.getRoad(waypoints)
        if (road.mStatus != Road.STATUS_OK){
            Toast.makeText(this, "Errore nel caricamento di road - status = "   road.mStatus, Toast.LENGTH_SHORT).show()
        }
        println("passo4 - CreoPolilinea")
        val roadOverlay: Polyline = RoadManager.buildRoadOverlay(road)
        println("passo5 - AggiungoPolilineaAllaMappa")
        mapView.overlays.add(roadOverlay)
        mapView.invalidate()

        // crea checkpoint lungo il percorso
        val nodeIcon: Drawable? = ResourcesCompat.getDrawable(resources, R.drawable.marker_node, null)
        for (i: Int in road.mNodes.indices){
            val node: RoadNode = road.mNodes[i]
            val nodeMarker: Marker = Marker(mapView)
            nodeMarker.position = node.mLocation
            nodeMarker.icon = nodeIcon
            nodeMarker.title = "Passo $i"
            mapView.overlays.add(nodeMarker)

            // aggiunge informazioni nelle finestre dei checkpoint
            nodeMarker.snippet = node.mInstructions
            nodeMarker.subDescription = Road.getLengthDurationText(this,node.mLength, node.mDuration)
            // var icon: Drawable = resources.getDrawable(R.drawable.ic_continue)
            // nodeMarker.image = icon
        }
    }

}

this is my xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@ id/location"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/location"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@ id/map" />

        <EditText style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:id="@ id/editTextLatitudine"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:ems="10"
            android:inputType="numberDecimal"
            android:hint="@string/latitudine"
             />

        <EditText style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:id="@ id/editTextLongitudine"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:ems="10"
            android:inputType="numberDecimal"
            android:hint="@string/longitudine"/>

    </LinearLayout>

    <org.osmdroid.views.MapView
        android:id="@ id/map"
        tilesource="Mapnik"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout_editor_absoluteX="-181dp"
        tools:layout_editor_absoluteY="57dp">

    </org.osmdroid.views.MapView>

</LinearLayout>

and this my gradle:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "uk.co.lorenzopulcinelli.trackapp"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    implementation 'androidx.preference:preference:1.2.0' //aggiunta per utilizzare import androidx.preference.PreferenceManager
    implementation 'com.google.android.gms:play-services-location:20.0.0' //aggiunta per richiedere permessi localizzazione

    implementation 'androidx.core:core-ktx:1.8.0'
    implementation 'androidx.appcompat:appcompat:1.4.2'
    implementation 'com.google.android.material:material:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    implementation files ('/home/acer/AndroidStudioProjects/TrackApp/app/libs/osmbonuspack_6.9.0.aar')
    implementation files ('/home/acer/AndroidStudioProjects/TrackApp/app/libs/osmdroid-android-6.1.13.aar')

    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.google.code.gson:gson:2.8.9'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
    implementation 'com.squareup.okhttp3:okhttp:4.10.0'

}

CodePudding user response:

A TextInputEditText is (as the docs say):

A special sub-class of EditText designed for use as a child of TextInputLayout.

Using this class allows us to display a hint in the IME when in 'extract' mode and provides accessibility support for TextInputLayout.

It's a special kind of EditText that goes in a TextInputLayout basically (which you're not using).

So a TextInputEditText is an EditText (because that's its superclass), but an EditText is not a TextInputEditText, in the same way an Integer is a Number, but a Number is not an Integer - and if you assume a Number object is also an Integer when it isn't, it'll crash when you cast it to that invalid type.

You're using plain EditTexts in your XML (technically AppCompatEditTexts like in the error, they're automatically converted and AppCompatEditText is the superclass of TextInputEditText - don't worry about it, basically). So when you do

findViewById<TextInputEditText>(R.id.editTextLatitudine)

The view with that ID is an EditText and you're trying to cast it to a TextInputEditText, which it ain't. Cast fails, you get a crash!


You're not even using a TextInputLayout anyway, so you have no use for TextInputEditTexts. Just treat them as plain EditTexts in your code (which is what they are!) like in JustSightseeing's answer

CodePudding user response:

You cannot cast an editText to TextInputLayout. That is because they are different items with different types. Change these 2 lines of code:

private lateinit var editTextLatitudine: TextInputEditText
private lateinit var editTextLongitudine: TextInputEditText

and those 2:

 // traccia percorso tra i punti degli editText
editTextLatitudine = findViewById<TextInputEditText>(R.id.editTextLatitudine)
editTextLongitudine = findViewById<TextInputEditText>(R.id.editTextLongitudine)

to:

 // traccia percorso tra i punti degli editText
editTextLatitudine = findViewById<EditText>(R.id.editTextLatitudine)
editTextLongitudine = findViewById<EditText>(R.id.editTextLongitudine)
private lateinit var editTextLatitudine: EditText
private lateinit var editTextLongitudine: EditText

as shown here, AppCompatEditText extends EditText, so you just have to change the type of those and it should run

  • Related