我已经创建了一个应用程序,它为用户提供了五个选项。他们可以从这些选项中选择一个城市,并被引导到一个新的屏幕,在那里他们将看到该城市的MapView以及3个标记。我想在用户单击标记时创建一个customer InfoWindow。因此,我创建了一个名为infowindow.xml的自定义文件,并在其中创建了InfoWindow的布局。
然而,我不太确定如何在我的MapView中实现它。我已经提供了下面所有相关的代码:
任何帮助或指导都将不胜感激。
MainActivity.kt
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.tanav.tanavsharma_mapd711_assignment3.models.Place
import com.tanav.tanavsharma_mapd711_assignment3.models.UserMap
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/* Setting the layout manager on the recycler view
************* layout manager is responsible for telling the
************* recycler view how to layout the views on the
************* screen
* Set adapter on the recycler view
*/
val cityMaps = findViewById<RecyclerView>(R.id.cityMaps)
val userMaps = generateSampleData()
cityMaps.layoutManager = LinearLayoutManager(this)
cityMaps.adapter = MapsAdapter(this, userMaps, object : MapsAdapter.OnClickListener{
override fun onItemClick(position: Int) {
val intent = Intent(this@MainActivity, DisplayMapActivity::class.java)
intent.putExtra("UserMap", userMaps[position])
startActivity(intent)
}
})
}
private fun generateSampleData(): List<UserMap> {
return listOf(
UserMap(
"Toronto",
listOf(
Place("CN Tower Cruise", "290 Bremner Blvd, Toronto, ON M5V 3L9", "416-900-0098", "Open 9:00 AM to 6:30 PM",43.642905, -79.386900),
Place("Rail Way Cruise", "255 Bremner Blvd, Toronto, ON M5V 3M9", "416-900-0098","Open 9:00 AM to 6:30 PM",43.640805, -79.385945),
Place("Pinkbery Cruise", "161 King St E, Toronto, ON M5C 1G9", "416-900-0098","Open 9:00 AM to 6:30 PM",43.650050, -79.372404)
)
),
UserMap("Mississauga",
listOf(
Place("Celebration Cruise", "300 City Centre Dr, Mississauga, ON L5B 3C1", "416-900-0098","Open 9:00 AM to 6:30 PM",43.588070, -79.643000),
Place("Golden Cruise", "1177 Central Pkwy W Unit 59, Mississauga, ON L5C 4P3", "416-900-0098","Open 9:00 AM to 6:30 PM",43.567164, -79.660391),
Place("Waterfall Cruise", "1180 Lakeshore Rd W, Mississauga, ON L5H 3L1", "416-900-0098","Open 9:00 AM to 6:30 PM",43.519416, -79.603003)
)),
UserMap("Oakville",
listOf(
Place("Lions Valley Cruise", "1227 Lions Valley Park Rd, Oakville, ON L6M 4L8", "416-900-0098","Open 9:00 AM to 6:30 PM",43.459962, -79.748594),
Place("Lake Side Cruise", "2 Navy St, Oakville, ON L6J 2Y5", "416-900-0098","Open 9:00 AM to 6:30 PM",43.441586,-79.666197),
Place("Coronation Cruise", "1426 Lakeshore Rd W, Oakville, ON L6L 1G2","416-900-0098","Open 9:00 AM to 6:30 PM",43.409619, -79.692486),
)
),
UserMap("Hamilton",
listOf(
Place("Heritage Cruise", "9280 Airport Rd, Mount Hope, ON L0R 1W0", "416-900-0098","Open 9:00 AM to 6:30 PM",43.159565, -79.925317),
Place("Red Hill Cruise", "768 Mountain Brow Blvd, Hamilton, ON L8W 1R6", "416-900-0098","Open 9:00 AM to 6:30 PM",43.200056, -79.819558),
Place("Spencer Cruise", "001 Harvest Rd, Dundas, ON L9H 4W2", "416-900-0098","Open 9:00 AM to 6:30 PM",43.281500, -79.980189),
)
),
UserMap("North York",
listOf(
Place("Fairview Cruise", "1800 Sheppard Ave E, Toronto, ON M2J 5A7", "416-900-0098","Open 9:00 AM to 6:30 PM",43.777332, -79.344127),
Place("Pures Cruise", "1450 Midland Ave suite 200&300, Scarborough, ON M1P 4Z8","416-900-0098", "Open 9:00 AM to 6:30 PM",43.751293, -79.265983),
Place("Leion Cruise", "430 Nugget Ave, Scarborough, ON M1S 5E1", "416-900-0098","Open 9:00 AM to 6:30 PM",43.798544, -79.243165),
)
)
)
}
}DisplayMapActivity.kt
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.google.android.gms.maps.model.MarkerOptions
import com.tanav.tanavsharma_mapd711_assignment3.databinding.ActivityDisplayMapBinding
import com.tanav.tanavsharma_mapd711_assignment3.models.UserMap
class DisplayMapActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
private lateinit var binding: ActivityDisplayMapBinding
private lateinit var userMap: UserMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDisplayMapBinding.inflate(layoutInflater)
setContentView(binding.root)
userMap = intent.getSerializableExtra("UserMap") as UserMap
supportActionBar?.title = userMap.title
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.map_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(item.itemId == R.id.standard){
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL)
}else if(item.itemId == R.id.satellite){
mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE)
}else if(item.itemId == R.id.hybrid){
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID)
}
return super.onOptionsItemSelected(item)
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
// Add a marker in the place of click and move the camera
val boundsBuilder = LatLngBounds.Builder()
for(place in userMap.places){
val latlng = LatLng(place.latitude, place.longitude)
boundsBuilder.include(latlng)
mMap.addMarker(MarkerOptions().position(latlng).title(place.title).snippet(place.address).snippet(place.number).snippet(place.hours))
}
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 1000, 1000, 0))
}MapsAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.tanav.tanavsharma_mapd711_assignment3.models.UserMap
class MapsAdapter(val context: Context, val userMaps: List<UserMap>, val onClickListener: OnClickListener) : RecyclerView.Adapter<MapsAdapter.ViewHolder>() {
interface OnClickListener {
fun onItemClick(position: Int)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(android.R.layout.simple_expandable_list_item_1, parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val userMap = userMaps[position]
holder.itemView.setOnClickListener {
onClickListener.onItemClick(position)
}
val textViewTitle = holder.itemView.findViewById<TextView>(android.R.id.text1)
textViewTitle.text = userMap.title
}
override fun getItemCount() = userMaps.size
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
}下面是我用过的类,Place.kt
import java.io.Serializable
data class Place(val title: String, val address: String, val number: String, val hours: String, val latitude: Double, val longitude: Double ) : Serializable& UserMap.kt
import java.io.Serializable
data class UserMap(val title: String, val places: List<Place>) : Serializableinfowindow.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/common_google_signin_btn_icon_dark_normal_background"
android:orientation="horizontal"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#99A2D6"
android:orientation="vertical">
<ImageView
android:id="@+id/pictureStreet"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:layout_gravity="start"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#000"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:ellipsize="end"
android:maxLines="10"
android:textColor="#000"
android:textSize="14sp" />
<TextView
android:id="@+id/number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:ellipsize="end"
android:maxLines="10"
android:textColor="#000"
android:textSize="14sp" />
<TextView
android:id="@+id/hours"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:ellipsize="end"
android:maxLines="10"
android:textColor="#000"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>CustomInfoWindowAdapter.kt
import android.app.Activity
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.Marker
class CustomInfoWindowAdapter(private val layoutInflater: LayoutInflater): GoogleMap.InfoWindowAdapter {
var mlayoutInflater = layoutInflater
var mWindow = (layoutInflater as Activity).layoutInflater.inflate(R.layout.infowindow, null)
private fun rendowWindowText(marker: Marker, view: View){
val tvTitle = view.findViewById<TextView>(R.id.title)
val tvAddress = view.findViewById<TextView>(R.id.address)
val tvNumber = view.findViewById<TextView>(R.id.number)
val tvHours = view.findViewById<TextView>(R.id.hours)
val ivPicture = view.findViewById<ImageView>(R.id.pictureStreet)
tvTitle.text = marker.title
tvAddress.text = marker.address // red underline
tvNumber.text = marker.number // red underline
tvHours.text = marker.hours // red underline
ivPicture.setImageDrawable(R.drawable.cntower) //red underline
}
override fun getInfoWindow(marker: Marker): View {
//Inflate and return your infolayout
rendowWindowText(marker, mWindow)
return mWindow
}
override fun getInfoContents(marker: Marker): View {
//Inflate and return your infolayout
rendowWindowText(marker, mWindow)
return mWindow
}
}发布于 2021-10-31 23:25:06
首先,通过扩展GoogleMap.InfoWindowAdapter创建一个定制的InfoViewAdapter类,如下所示
class CustomInfoWindowAdapter(private val layoutInflater: LayoutInflater):GoogleMap.InfoWindowAdapter {
override fun getInfoWindow(p0: Marker): View {
//Inflate and return your infolayout
return #YourInfoView
}
override fun getInfoContents(p0: Marker): View {
//Inflate and return your infolayout
return #YourInfoView
}
}然后,在您的onMapReady函数中,将您的适配器分配给map
mMap.setInfoWindowAdapter(CustomInfoWindowAdapter(layoutInflater))就是这样。它应该会在点击标记时显示你的信息视图
https://stackoverflow.com/questions/69790382
复制相似问题