Merge pull request #1 from Aviortheking/Page2

Page 2 Complété
This commit is contained in:
Florian Bouillon 2021-02-19 15:22:46 +01:00 committed by GitHub
commit f017563668
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 394 additions and 20 deletions

View File

@ -38,7 +38,25 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.2.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
// Retrofit
implementation 'com.google.code.gson:gson:2.8.4'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
implementation "com.android.support:cardview-v7:29.1.1"
implementation 'com.android.support:recyclerview-v7:29.1.1'
implementation 'com.squareup.picasso:picasso:2.71828'
//Picasso
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.squareup.okhttp:okhttp:2.2.0'
implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'
}
apply plugin: 'kotlin-android-extensions'

View File

@ -1,14 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ca_contest">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.CA_Contest">
<activity
android:name=".CountrySelectorActivity"
android:label="@string/title_activity_country_selector"
android:theme="@style/Theme.CA_Contest.NoActionBar"></activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -0,0 +1,74 @@
package com.example.ca_contest
import com.example.ca_contest.adapters.CountryAdapter
import android.app.ProgressDialog
import android.content.Intent
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.ca_contest.api.ApiClient
import com.example.ca_contest.api.Country
import kotlinx.android.synthetic.main.activity_country_selector.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import kotlin.collections.ArrayList
class CountrySelectorActivity : AppCompatActivity() {
private var data: ArrayList<Country> = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_country_selector)
// Progress Bar
val progressDialog = ProgressDialog(this)
progressDialog.setTitle("Récupération des pays...")
progressDialog.setCancelable(false)
progressDialog.show()
// Initialize Recycler
val recycler = findViewById<RecyclerView>(R.id.list)
recycler.setHasFixedSize(true)
val layoutManager = LinearLayoutManager(this)
recycler.layoutManager = layoutManager
val adapter = CountryAdapter(data)
recycler.adapter = adapter
// Fetch Countries
ApiClient.getClient.getCountries().enqueue(object : Callback<List<Country>> {
override fun onResponse(call: Call<List<Country>>?, response: Response<List<Country>>?) {
progressDialog.dismiss()
data.addAll(response!!.body()!!)
adapter.update(data.clone() as ArrayList<Country>)
recycler.adapter?.notifyDataSetChanged()
}
override fun onFailure(call: Call<List<Country>>?, t: Throwable?) {
progressDialog.dismiss()
}
})
// Input Text and Button
val textView = findViewById<TextView>(R.id.text)
var btn = findViewById<Button>(R.id.validate)
btn.setOnClickListener {
adapter.update((data.filter { country -> country.name.contains(textView.text, true) } as ArrayList<Country>))
recycler.adapter?.notifyDataSetChanged()
}
}
}

View File

@ -1,11 +1,19 @@
package com.example.ca_contest
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var btn = findViewById<Button>(R.id.btnStartAnotherActivity)
btn.setOnClickListener {
val intent = Intent(this, CountrySelectorActivity::class.java)
// start your next activity
startActivity(intent)
}
}
}

View File

@ -0,0 +1,71 @@
package com.example.ca_contest.adapters
import com.example.ca_contest.R
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.example.ca_contest.api.Country
import com.squareup.picasso.Picasso
class CountryAdapter(list: ArrayList<Country>) : RecyclerView.Adapter<CountryAdapter.CountryViewHolder>() {
private var list: ArrayList<Country> = ArrayList()
init {
this.list = list
}
// Create the view Holder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CountryViewHolder {
val viewMemo: View =
LayoutInflater.from(parent.context).inflate(R.layout.country_selector_item, parent, false)
return CountryViewHolder(viewMemo)
}
// Bind each items
override fun onBindViewHolder(holder: CountryViewHolder, position: Int) {
holder.name?.text = list[position].name
holder.capital?.text = "Capital : " + list[position].capital
holder.region?.text = "Continent : " + list[position].region
Picasso.get()
.load("http://www.geognos.com/api/en/countries/flag/" + list[position].alpha2Code + ".png")
.into(holder.image!!)
}
// Update the list
fun update(list: ArrayList<Country>) {
this.list = list
}
override fun getItemCount(): Int {
return list.size
}
inner class CountryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var name: TextView? = null
var capital: TextView? = null
var region: TextView? = null
var image: ImageView? = null
init {
name = itemView.findViewById(R.id.name)
capital = itemView.findViewById(R.id.capital)
region = itemView.findViewById(R.id.region)
image = itemView.findViewById(R.id.image)
itemView.setOnClickListener {
val context = itemView.context
// Intent to Calendar
Toast.makeText(
context, name?.text, Toast.LENGTH_LONG
).show()
}
}
}
}

View File

@ -0,0 +1,35 @@
package com.example.ca_contest.api
import com.google.gson.GsonBuilder
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object ApiClient {
var BASE_URL:String="https://restcountries.eu/"
val getClient: ApiInterface
get() {
// Initialize JSON Builder
val gson = GsonBuilder()
.setLenient()
.create()
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
// Initialize Retrofit
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
// return the response a a Model
return retrofit.create(ApiInterface::class.java)
}
}

View File

@ -0,0 +1,11 @@
package com.example.ca_contest.api
import retrofit2.Call
import retrofit2.http.GET
interface ApiInterface {
@GET("rest/v2/all")
fun getCountries(): Call<List<Country>>
}

View File

@ -0,0 +1,21 @@
package com.example.ca_contest.api
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
data class Country(
@Expose
@SerializedName("name")
val name: String,
@Expose
@SerializedName("capital")
val capital: String,
@Expose
@SerializedName("region")
val region: String,
@Expose
@SerializedName("alpha2Code")
val alpha2Code: String
) {}

View File

@ -1,15 +0,0 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package CA_Contest
class App {
val greeting: String
get() {
return "Hello World!"
}
}
fun main() {
println(App().greeting)
}

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CountrySelectorActivity">
<EditText
android:id="@+id/text"
android:layout_width="325dp"
android:layout_height="40dp"
android:background="#eee"
android:hint="Nom du pays"
android:inputType="textCapSentences"
android:maxLines="1"
android:textColor="@android:color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/validate"
android:layout_width="0dp"
android:layout_height="40dp"
android:background="#eee"
android:text="OK"
android:textColor="@android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/text"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text"
tools:layout_editor_absoluteX="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -15,4 +15,15 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnStartAnotherActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:background="#397bb2"
android:padding="20sp"
android:text="Start Another Activity"
android:textColor="#FFF"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="86dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/image"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
app:layout_constraintStart_toEndOf="@+id/image"
app:layout_constraintTop_toTopOf="parent"
tools:text="Nom Pays" />
<TextView
android:id="@+id/capital"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
app:layout_constraintStart_toEndOf="@+id/image"
app:layout_constraintTop_toBottomOf="@+id/name"
tools:text="Capital: Capital" />
<TextView
android:id="@+id/region"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:textColor="@android:color/black"
app:layout_constraintStart_toEndOf="@+id/image"
app:layout_constraintTop_toBottomOf="@+id/capital"
tools:text="Continent: Continent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/nav_graph"
app:startDestination="@id/FirstFragment">
<fragment
android:id="@+id/FirstFragment"
android:name="com.example.ca_contest.FirstFragment"
android:label="@string/first_fragment_label"
tools:layout="@layout/fragment_first">
<action
android:id="@+id/action_FirstFragment_to_SecondFragment"
app:destination="@id/SecondFragment" />
</fragment>
<fragment
android:id="@+id/SecondFragment"
android:name="com.example.ca_contest.SecondFragment"
android:label="@string/second_fragment_label"
tools:layout="@layout/fragment_second">
<action
android:id="@+id/action_SecondFragment_to_FirstFragment"
app:destination="@id/FirstFragment" />
</fragment>
</navigation>

View File

@ -0,0 +1,3 @@
<resources>
<dimen name="fab_margin">16dp</dimen>
</resources>

View File

@ -1,3 +1,12 @@
<resources>
<string name="app_name">CA_Contest</string>
<string name="title_activity_country_selector">CountrySelectorActivity</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="next">Next</string>
<string name="previous">Previous</string>
<string name="hello_first_fragment">Hello first fragment</string>
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
</resources>

View File

@ -13,4 +13,13 @@
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
<style name="Theme.CA_Contest.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="Theme.CA_Contest.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="Theme.CA_Contest.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

View File

@ -6,8 +6,9 @@ buildscript {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.1"
classpath 'com.android.tools.build:gradle:4.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}

View File

@ -1,6 +1,6 @@
#Fri Feb 19 09:41:29 CET 2021
#Fri Feb 19 10:26:45 CET 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip