diff --git a/.idea/compiler.xml b/.idea/compiler.xml index b589d56..b86273d 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index aee4b00..fa0dd9f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -10,10 +10,17 @@ - + + + + \ No newline at end of file diff --git a/NationalPark.mp4 b/NationalPark.mp4 new file mode 100644 index 0000000..2e71d5e Binary files /dev/null and b/NationalPark.mp4 differ diff --git a/app/build.gradle b/app/build.gradle index bfe7678..078c9ee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -47,4 +47,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' -} \ No newline at end of file + implementation 'com.codepath.libraries:asynchttpclient:2.2.0' + implementation 'com.github.bumptech.glide:glide:4.12.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' +} diff --git a/app/src/main/java/com/codepath/nationalparks/NationalPark.kt b/app/src/main/java/com/codepath/nationalparks/NationalPark.kt index bff3fa3..604c2ed 100644 --- a/app/src/main/java/com/codepath/nationalparks/NationalPark.kt +++ b/app/src/main/java/com/codepath/nationalparks/NationalPark.kt @@ -25,8 +25,14 @@ class NationalPark { @SerializedName("states") var location: String? = null - //TODO parkImageUrl + @SerializedName("images") + var images: List? = null + // Convenience property to access the first image’s URL + val imageUrl: String? get() = images?.firstOrNull()?.url - //TODO-STRETCH-GOALS + class Image { + @SerializedName("url") + var url: String? = null + } } diff --git a/app/src/main/java/com/codepath/nationalparks/NationalParksFragment.kt b/app/src/main/java/com/codepath/nationalparks/NationalParksFragment.kt index 9a2546d..085f420 100644 --- a/app/src/main/java/com/codepath/nationalparks/NationalParksFragment.kt +++ b/app/src/main/java/com/codepath/nationalparks/NationalParksFragment.kt @@ -1,6 +1,7 @@ package com.codepath.nationalparks import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -9,36 +10,42 @@ import androidx.core.widget.ContentLoadingProgressBar import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.codepath.asynchttpclient.AsyncHttpClient +import com.codepath.asynchttpclient.RequestParams +import com.codepath.asynchttpclient.callback.JsonHttpResponseHandler +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import okhttp3.Headers +import org.json.JSONArray // --------------------------------// // CHANGE THIS TO BE YOUR API KEY // // --------------------------------// -private const val API_KEY = "" +private const val API_KEY = "0uZ6uWEVVJjaWWdR8T0ZgGi8rCNu6QHmWa1WN3cl" /* * The class for the only fragment in the app, which contains the progress bar, * recyclerView, and performs the network calls to the National Parks API. - */ class NationalParksFragment : Fragment(), OnListFragmentInteractionListener { - /* + /* * Constructing the view */ - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - val view = inflater.inflate(R.layout.fragment_national_parks_list, container, false) - val progressBar = view.findViewById(R.id.progress) as ContentLoadingProgressBar - val recyclerView = view.findViewById(R.id.list) as RecyclerView - val context = view.context - - recyclerView.layoutManager = LinearLayoutManager(context) - - updateAdapter(progressBar, recyclerView) - return view - } + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.fragment_national_parks_list, container, false) + val progressBar = view.findViewById(R.id.progress) as ContentLoadingProgressBar + val recyclerView = view.findViewById(R.id.list) as RecyclerView + val context = view.context + + recyclerView.layoutManager = LinearLayoutManager(context) + + updateAdapter(progressBar, recyclerView) + return view + } /* * Updates the RecyclerView adapter with new data. This is where the @@ -48,53 +55,65 @@ class NationalParksFragment : Fragment(), OnListFragmentInteractionListener { progressBar.show() // Create and set up an AsyncHTTPClient() here + val client = AsyncHttpClient() + val params = RequestParams() + params["api_key"] = API_KEY // Using the client, perform the HTTP request + client[ + "https://developer.nps.gov/api/v1/parks", + params, + object : JsonHttpResponseHandler() { + /* + * The onSuccess function gets called when + * HTTP response status is "200 OK" + */ + override fun onSuccess( + statusCode: Int, + headers: Headers, + json: JsonHttpResponseHandler.JSON + ) { + // The wait for a response is over + progressBar.hide() + + val dataJSON = json.jsonObject.get("data") as JSONArray + val parksRawJSON = dataJSON.toString() + + // Create a Gson instance to help parse the raw JSON + val gson = Gson() + + // Tell Gson what type we’re expecting (a list of NationalPark objects) + val arrayParkType = object : TypeToken>() {}.type + + // Convert the raw JSON string into a list of actual NationalPark data models + val models: List = gson.fromJson(parksRawJSON, arrayParkType) + + recyclerView.adapter = NationalParksRecyclerViewAdapter(models, this@NationalParksFragment) + + // Look for this in Logcat: + Log.d("NationalParksFragment", "response successful") + } - /* Uncomment me once you complete the above sections! - { - /* - * The onSuccess function gets called when - * HTTP response status is "200 OK" - */ - override fun onSuccess( - statusCode: Int, - headers: Headers, - json: JsonHttpResponseHandler.JSON - ) { - // The wait for a response is over - progressBar.hide() - - //TODO - Parse JSON into Models - - val models : List = mutableListOf() // Fix me! - recyclerView.adapter = NationalParksRecyclerViewAdapter(models, this@NationalParksFragment) - - // Look for this in Logcat: - Log.d("NationalParksFragment", "response successful") - } - - /* - * The onFailure function gets called when - * HTTP response status is "4XX" (eg. 401, 403, 404) - */ - override fun onFailure( - statusCode: Int, - headers: Headers?, - errorResponse: String, - t: Throwable? - ) { - // The wait for a response is over - progressBar.hide() - - // If the error is not null, log it! - t?.message?.let { - Log.e("NationalParksFragment", errorResponse) + /* + * The onFailure function gets called when + * HTTP response status is "4XX" (eg. 401, 403, 404) + */ + override fun onFailure( + statusCode: Int, + headers: Headers?, + errorResponse: String, + t: Throwable? + ) { + // The wait for a response is over + progressBar.hide() + + // If the error is not null, log it! + t?.message?.let { + Log.e("NationalParksFragment", errorResponse) + } } } - }] - */ - + ] } /* diff --git a/app/src/main/java/com/codepath/nationalparks/NationalParksRecyclerViewAdapter.kt b/app/src/main/java/com/codepath/nationalparks/NationalParksRecyclerViewAdapter.kt index e88c369..4d47272 100644 --- a/app/src/main/java/com/codepath/nationalparks/NationalParksRecyclerViewAdapter.kt +++ b/app/src/main/java/com/codepath/nationalparks/NationalParksRecyclerViewAdapter.kt @@ -3,9 +3,10 @@ package com.codepath.nationalparks import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView -import com.codepath.nationalparks.R.id +import com.bumptech.glide.Glide /** * [RecyclerView.Adapter] that can display a [NationalPark] and makes a call to the @@ -27,9 +28,10 @@ class NationalParksRecyclerViewAdapter( inner class ParkViewHolder(val mView: View) : RecyclerView.ViewHolder(mView) { var mItem: NationalPark? = null - // TODO: Step 4a - Add references for remaining views from XML - val mParkName: TextView = mView.findViewById(id.park_name) as TextView - val mParkDescription: TextView = mView.findViewById(id.park_description) as TextView + val mParkImage: ImageView = mView.findViewById(R.id.park_image) as ImageView + val mParkName: TextView = mView.findViewById(R.id.park_name) as TextView + val mParkLocation: TextView = mView.findViewById(R.id.park_location) as TextView + val mParkDescription: TextView = mView.findViewById(R.id.park_description) as TextView override fun toString(): String { return mParkName.toString() + " '" + mParkDescription.text + "'" @@ -39,13 +41,16 @@ class NationalParksRecyclerViewAdapter( override fun onBindViewHolder(holder: ParkViewHolder, position: Int) { val park = parks[position] - // TODO: Step 4b - Bind the park data to the views holder.mItem = park holder.mParkName.text = park.name + holder.mParkLocation.text = park.location holder.mParkDescription.text = park.description - // TODO: Step 4c - Use Glide to load the first image - + val imageUrl = park.imageUrl + Glide.with(holder.mView) + .load(imageUrl) + .centerInside() + .into(holder.mParkImage) // Sets up click listener for this park item holder.mView.setOnClickListener { diff --git a/app/src/main/res/layout/fragment_national_park.xml b/app/src/main/res/layout/fragment_national_park.xml index 823bf83..60b9875 100644 --- a/app/src/main/res/layout/fragment_national_park.xml +++ b/app/src/main/res/layout/fragment_national_park.xml @@ -2,32 +2,62 @@ + android:padding="12dp"> + + - + android:layout_marginStart="16dp" + android:textColor="@android:color/black" + android:textSize="18sp" + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/park_image" + app:layout_constraintTop_toTopOf="@+id/park_image" + tools:text="Yellowstone National Park" /> - + tools:text="Visit Yellowstone and experience the world's first national park." /> - - +