I've created a Location class and when I click on Cinemas in MainActivity, I want to open another activity that contains the list of Location objects. For this goal I have created a custom location_list_item layout file and a custom ArrayAdapter. For some reason, when I click on Cinemas, my app crashes. Why?
MainActivity.java
package com.example.android.tourguide;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View cinemasView = findViewById(R.id.cinemas_layout);
cinemasView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,
CinemasActivity.class);
startActivity(intent);
}
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#fff8e1"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/main_activity_title"
android:textSize="30sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="16dp"/>
<LinearLayout
android:id="@+id/cinemas_layout"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#4a148c">
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:src="@drawable/category_cinemas"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/category_cinemas"
android:textSize="25sp"
android:textColor="@android:color/white"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="@android:color/darker_gray" />
<LinearLayout
android:id="@+id/restaurants_layout"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#4a148c">
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:src="@drawable/category_restaurants"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/category_restaurants"
android:textSize="25sp"
android:textColor="@android:color/white"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="@android:color/darker_gray" />
<LinearLayout
android:id="@+id/gyms_layout"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#4a148c">
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:src="@drawable/category_gyms"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/category_gyms"
android:textSize="25sp"
android:textColor="@android:color/white"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="@android:color/darker_gray" />
<LinearLayout
android:id="@+id/parks_layout"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#4a148c">
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:src="@drawable/category_parks"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/category_parks"
android:textSize="25sp"
android:textColor="@android:color/white"/>
</LinearLayout>
</LinearLayout>
location_category_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/location_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/location_hours_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="Hours"
android:textStyle="bold"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/location_working_days"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
tools:text="Every Day" />
<TextView
android:id="@+id/location_working_hours"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
tools:text="09:00 – 00:00" />
</LinearLayout>
<TextView
android:id="@+id/location_address_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="Address"
android:textStyle="bold"/>
<TextView
android:id="@+id/location_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
tools:text="09:00 – 00:00" />
<TextView
android:id="@+id/location_phone_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="Phone"
android:textStyle="bold"/>
<TextView
android:id="@+id/location_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
tools:text="+7 (555) 555-55-55" />
</LinearLayout>
Location.java
package com.example.android.tourguide;
import androidx.annotation.NonNull;
public class Location {
private int mImageResourceId;
private String mAddress;
private String mPhone;
private String mWorkingDays;
private String mWorkingHours;
public Location(int imageResourceId, String address, String phone,
String workingDays, String workingHours) {
mImageResourceId = imageResourceId;
mAddress = address;
mPhone = phone;
mWorkingDays = workingDays;
mWorkingHours = workingHours;
}
public int getImageResourceId() {
return mImageResourceId;
}
public String getAddress() {
return mAddress;
}
public String getPhone() {
return mPhone;
}
public String getWorkingDays() {
return mWorkingDays;
}
public String getWorkingHours() {
return mWorkingHours;
}
@NonNull
@Override
public String toString() {
return mImageResourceId + mAddress + mWorkingDays + mWorkingDays + mPhone;
}
}
LocationAdapter.java
package com.example.android.tourguide;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class LocationAdapter extends ArrayAdapter<Location> {
/**
* This is our own custom constructor (it doesn't mirror a superclass constructor).
* The context is used to inflate the layout file, and the list is the data we want
* to populate into the lists.
*
* @param context The current context. Used to inflate the layout file.
* @param locations A List of Location objects to display in a list
*/
public LocationAdapter(Activity context, ArrayList<Location> locations) {
// Here, we initialize the ArrayAdapter's internal storage for the context and the list.
// the second argument is used when the ArrayAdapter is populating a single TextView.
// Because this is a custom adapter for one ImageView and 4 TextViews, the adapter is not
// going to use this second argument, so it can be any value. Here, we used 0.
super(context, 0, locations);
}
/**
* Provides a view for an AdapterView (ListView, GridView, etc.)
*
* @param position The position in the list of data that should be displayed in the
* list item view.
* @param convertView The recycled view to populate.
* @param parent The parent ViewGroup that is used for inflation.
* @return The View for the position in the AdapterView.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Check if the existing view is being reused, otherwise inflate the view
View listItemView = convertView;
if (listItemView == null)
{
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.location_category_list_item, parent,
false);
}
// Get the {@link Location} object located at this position in the list
Location currentLocation = getItem(position);
// Find the ImageView in the location_category_list_item.xml layout
// with the ID location_image
ImageView image = listItemView.findViewById(R.id.location_image);
// Get the image resource ID from the current Location object and
// set the image to imageView
image.setImageResource(currentLocation.getImageResourceId());
// Find the TextView in the location_category_list_item.xml layout
// with the ID location_working_days
TextView workingDaysTextView = listItemView.findViewById(R.id.location_working_days);
// Get the working days from the current Location object and
// set this text on the workingDaysTextView
workingDaysTextView.setText(currentLocation.getWorkingDays());
// Find the TextView in the location_category_list_item.xml layout
// with the ID location_working_hours
TextView workingHoursTextView = listItemView.findViewById(R.id.location_working_hours);
// Get the working hours from the current Location object and
// set this text on the workingHoursTextView
workingHoursTextView.setText(currentLocation.getWorkingHours());
// Find the TextView in the location_category_list_item.xml layout
// with the ID location_address
TextView addressTextView = listItemView.findViewById(R.id.location_address);
// Get the address from the current Location object and
// set this text on the addressTextView
addressTextView.setText(currentLocation.getAddress());
// Find the TextView in the location_category_list_item.xml layout
// with the ID location_phone
TextView phoneTextView = listItemView.findViewById(R.id.location_phone);
// Get the address from the current Location object and
// set this text on the phoneTextView
phoneTextView.setText(currentLocation.getPhone());
// Return the whole list item layout
// so that it can be shown in the ListView
return listItemView;
}
}
CinemasActivity.java
package com.example.android.tourguide;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
public class CinemasActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.location_category_list_item);
//Create a list of cinemas
final ArrayList<Location> locations = new ArrayList<>();
locations.add(new Location(R.drawable.cinemas_byl,
"Zhukova mikrorayon, 38",
"+7 (929) 002-20-09",
"Every Day",
"09:00 – 00:00"));
locations.add(new Location(R.drawable.cinemas_charly,
"Ol'minskogo mikrorayon, 17",
"+7 (472) 523-34-56",
"Every Day",
"09:30 – 02:00"));
locations.add(new Location(R.drawable.cinemas_cinema_5,
"Molodezhnyy Proyezd, 10",
"+7 (472) 523-37-27",
"Every Day",
"09:00 – 00:00"));
// Create an {@link LocationAdapter}, whose data source is a list of
// {@link Locations}. The adapter knows how to create list item views
// for each item in the list.
LocationAdapter locationAdapter = new LocationAdapter(this, locations);
// Get a reference to the ListView, and attach the adapter to the listView.
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(locationAdapter);
}
}