Fatal exception android:onClick when implementing sublayer visibility and map styles with ellipsis button

2634
4
Jump to solution
08-15-2023 03:43 PM
klebercj
New Contributor III

I am getting this error:

FATAL EXCEPTION: main
Process: com.example.app, PID: 2902
java.lang.IllegalStateException: Could not find method showSublayersDialog(View) in a parent or ancestor Context for android:onClick attribute defined on view class androidx.appcompat.widget.AppCompatImageButton with id 'ellipsisButton'

I've added an ellipsis button to the front of my app to control sub layer visibility and to change map style.  Everything worked great until I tried implementing the map style buttons.  Any help would be appreciated.

Here is my MainActivity

package com.example.app

import android.os.Bundle
import android.view.LayoutInflater
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.arcgismaps.ApiKey
import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.BasemapStyle
import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.mapping.ViewpointType
import com.arcgismaps.mapping.layers.ArcGISMapImageLayer
import com.arcgismaps.mapping.view.MapView
import com.example.app.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private val activityMainBinding: ActivityMainBinding by lazy {
DataBindingUtil.setContentView(this, R.layout.activity_main)
}

private val mapView: MapView by lazy {
activityMainBinding.mapView
}

private lateinit var arcgisImageryIcon: ImageView
private lateinit var osmStreetsIcon: ImageView
private lateinit var map: ArcGISMap

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)

val versionTextView = binding.versionTextView
val versionName = packageManager.getPackageInfo(packageName, 0).versionName
val versionText = resources.getString(R.string.version_text) + versionName
versionTextView.text = versionText

lifecycle.addObserver(mapView)

setApiKey()

setupMap()
}

private fun setupMap() {
val map = ArcGISMap(BasemapStyle.ArcGISImagery)
mapView.map = map

val mapServiceUrl =
"https://...../MapServer"
val mapImageLayer = ArcGISMapImageLayer(mapServiceUrl)
map.operationalLayers.add(mapImageLayer)

val viewpoint = Viewpoint(xx.xxx, -xxx.xxx, 420000.0)
mapView.setViewpoint(viewpoint)
}

private fun setApiKey() {
ArcGISEnvironment.apiKey =
ApiKey.create("xxx")
}

fun showSublayersDialog() {
val dialogView = LayoutInflater.from(this).inflate(R.layout.sublayers_dialog, null)

val builder = AlertDialog.Builder(this)
.setTitle("Sublayers")
.setView(dialogView)
.setPositiveButton("Close") { dialog, _ -> dialog.dismiss() }

val dialog = builder.create()
dialog.show()

val sublayersContainer: LinearLayout =
dialogView.findViewById(R.id.checkBoxGroup)

val mapImageLayer =
mapView.map?.operationalLayers?.get(0) as ArcGISMapImageLayer

if (mapImageLayer.mapImageSublayers.isNotEmpty()) {
for (sublayer in mapImageLayer.mapImageSublayers) {
val checkBox = CheckBox(this)
checkBox.text = sublayer.name
checkBox.isChecked = sublayer.isVisible
checkBox.setOnCheckedChangeListener { _, isChecked ->
sublayer.isVisible = isChecked
}
sublayersContainer.addView(checkBox)
}

arcgisImageryIcon.setOnClickListener {
val savedViewpoint =
mapView.getCurrentViewpoint(viewpointType = ViewpointType.CenterAndScale)
?.toJson()

map = ArcGISMap(BasemapStyle.ArcGISImagery)
mapView.map = map

if (savedViewpoint != null) {
val newViewpoint = Viewpoint.fromJsonOrNull(savedViewpoint)
if (newViewpoint != null) {
mapView.setViewpoint(newViewpoint)
}
}

arcgisImageryIcon.setBackgroundResource(R.drawable.selected_style_border)
osmStreetsIcon.setBackgroundResource(0)
}

osmStreetsIcon.setOnClickListener {
val savedViewpoint =
mapView.getCurrentViewpoint(viewpointType = ViewpointType.CenterAndScale)
?.toJson()

map = ArcGISMap(BasemapStyle.OsmStreets)
mapView.map = map

if (savedViewpoint != null) {
val newViewpoint = Viewpoint.fromJsonOrNull(savedViewpoint)
if (newViewpoint != null) {
mapView.setViewpoint(newViewpoint)
}
}

osmStreetsIcon.setBackgroundResource(R.drawable.selected_style_border)
arcgisImageryIcon.setBackgroundResource(0)
}
}
}
}


activities_main.xml

<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<com.arcgismaps.mapping.view.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="-37dp"
tools:layout_editor_absoluteY="173dp" />

<ImageButton
android:id="@+id/ellipsisButton"
android:layout_width="64dp"
android:layout_height="58dp"
android:layout_margin="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/layer_one"
android:onClick="showSublayersDialog"
android:src="@drawable/ic_ellipsis"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/versionTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/version_text"
android:layout_margin="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

sublayers_dialog.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">

<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:contentDescription="@string/sublayers_scrollview_description">

<LinearLayout
android:id="@+id/checkBoxGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>

</ScrollView>

<TextView
android:id="@+id/styleTitleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/map_style"
android:layout_marginTop="16dp" />

<!-- ArcGIS Imagery Icon -->
<ImageView
android:id="@+id/arcgisImageryIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="8dp"
android:src="@drawable/ic_satellite"
android:contentDescription="@string/arcgis_imagery"
android:background="?attr/selectableItemBackgroundBorderless" />

<!-- OSM Streets Icon -->
<ImageView
android:id="@+id/osmStreetsIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="8dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/osm_streets"
android:src="@drawable/ic_streets" />

</LinearLayout>

 

0 Kudos
1 Solution

Accepted Solutions
klebercj
New Contributor III

Current error is

FATAL EXCEPTION: main
Process: com.example.app, PID: 13858
java.lang.IllegalStateException: Could not execute method for android:onClick

 

View solution in original post

0 Kudos
4 Replies
Nicholas-Furness
Esri Regular Contributor

I'm not an Android/Kotlin developer, but it looks like your signature for showSublayersDialog() is wrong. It looks like you need it to accept a View parameter (e.g. showSublayersDialog(View v)). See this documentation on the android:onClick attribute.

The doc indicates that method should be public, but it looks like that's the default visibility for Kotlin, so you could be OK there.

0 Kudos
klebercj
New Contributor III

I previously had fun showSublayersDialog as

fun showSublayersDialog(view: View) {
val dialogView = LayoutInflater.from(this).inflate(R.layout.sublayers_dialog, null)

but Android Studio threw a warning that the parameter "view" wasn't being used.  So I removed it.  Adding it back in still causes a crash.

0 Kudos
Nicholas-Furness
Esri Regular Contributor

What's the crash once you have the correct signature for showSublayersDialog()? It should be different to the one in your original posting.

0 Kudos
klebercj
New Contributor III

Current error is

FATAL EXCEPTION: main
Process: com.example.app, PID: 13858
java.lang.IllegalStateException: Could not execute method for android:onClick

 

0 Kudos