Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .idea/deploymentTargetDropDown.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,28 @@ android {
}
buildFeatures{
viewBinding true
compose true
}
composeOptions{
kotlinCompilerExtensionVersion'1.1.1'
}
}

dependencies {
def lifecycle_version = "2.5.0-alpha03"
def fragment_version = '1.4.1'
def nav_version = '2.4.1'
def core_version = '1.6.0'
def compose_version = '1.1.1'

implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
implementation 'androidx.activity:activity-compose:1.4.0'

implementation "io.coil-kt:coil-compose:2.0.0-rc03"
implementation "androidx.core:core:$core_version"
implementation "com.google.android.gms:play-services-location:19.0.1"
implementation "androidx.fragment:fragment:$fragment_version"
implementation "androidx.fragment:fragment-ktx:$fragment_version"
Expand Down
7 changes: 4 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:name=".WeatherApplication"
android:allowBackup="true"
Expand All @@ -12,9 +15,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.WeatherApp">
<activity
android:name=".ForecastActivity"
android:exported="false" />
<service android:name=".NotificationService"/>
<activity
android:name=".MainActivity"
android:exported="true">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.components.ServiceComponent
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory

@Module
@InstallIn(ActivityComponent::class)
@InstallIn(ActivityComponent::class, ServiceComponent::class)
object ApplicationModule {
@Provides
fun provideApi(): Api {
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/java/com/example/weatherapp/DayForecast.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package com.example.weatherapp

import android.os.Parcelable
import com.squareup.moshi.Json
import kotlinx.android.parcel.Parcelize

@Parcelize
data class DayForecast(
@Json(name = "dt") val date: Long,
val sunrise: Long,
val sunset: Long,
val temp: ForecastTemp,
val pressure: Float,
val humidity: Int,
val weather: List<WeatherConditions>
)
val weather: List<WeatherConditions>,
val speed: Float
) : Parcelable

87 changes: 87 additions & 0 deletions app/src/main/java/com/example/weatherapp/ForecastDetailFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.example.weatherapp

import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.navArgs
import coil.compose.AsyncImage
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition

class ForecastDetailFragment : Fragment(){

private val args: ForecastDetailFragmentArgs by navArgs()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return ComposeView(requireContext()).apply {
setContent {
detailScreen()
}
}
}

@Composable
fun detailScreen(){
Column {
iconAndTemp()
description()
}
}

@Composable
fun iconAndTemp(){
val dayTemp = args.dayForecast.temp.day.toInt()
val iconName = args.dayForecast.weather.firstOrNull()!!.icon
val iconURL = "https://openweathermap.org/img/wn/${iconName}@2x.png"

Row(horizontalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxWidth()) {

AsyncImage(model = iconURL, contentDescription = null, modifier = Modifier.size(100.dp))
Text("$dayTemp °", fontSize = 75.sp)
}
}
@Preview
@Composable
fun description(){
val minTemp = args.dayForecast.temp.min
val maxTemp = args.dayForecast.temp.max
val humidity = args.dayForecast.humidity
val pressure = args.dayForecast.pressure
val windSpeed = args.dayForecast.speed
val description = args.dayForecast.weather.firstOrNull()!!.description
Column(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 15.dp, vertical = 5.dp)) {
Text(text = "Low: $minTemp", fontSize = 20.sp)
Text(text = "High: $maxTemp", fontSize = 20.sp)
Text(text = "Humidity: $humidity %", fontSize = 20.sp)
Text(text = "Pressure: $pressure hPa", fontSize = 20.sp)
Text(text = "Wind Speed: $windSpeed", fontSize = 20.sp)
Text(text = "$description", fontSize = 20.sp)
}
}

}
12 changes: 11 additions & 1 deletion app/src/main/java/com/example/weatherapp/ForecastFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package com.example.weatherapp

import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
Expand All @@ -25,7 +27,15 @@ class ForecastFragment: Fragment(R.layout.fragment_forecast) {
super.onResume()
viewModel.loadData(args.coordinates)
viewModel.dailyForecast.observe(this){ dailyForecast ->
recyclerView.adapter = ForecastRecyclerViewAdapter(dailyForecast.forecastList)
recyclerView.adapter = ForecastRecyclerViewAdapter(
dailyForecast.forecastList,
object: ItemClicked{
override fun onItemClicked(info: DayForecast) {
val action = ForecastFragmentDirections
.actionForecastFragmentToForecastDetailFragment(info)
findNavController().navigate(action)
}
})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.example.weatherapp
import android.os.Build
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.AdapterView
import androidx.annotation.RequiresApi
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
Expand All @@ -12,13 +13,12 @@ import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter

class ForecastRecyclerViewAdapter(private val data: List<DayForecast>)
class ForecastRecyclerViewAdapter(private val data: List<DayForecast>, private val itemClicked: ItemClicked )
: RecyclerView.Adapter<ForecastRecyclerViewAdapter.ViewHolder>() {

class ViewHolder(private val binding: ForecastDataBinding) : RecyclerView.ViewHolder(binding.root) {

@RequiresApi(Build.VERSION_CODES.O)
fun bind(info: DayForecast){
fun bind(info: DayForecast, itemClicked: ItemClicked){
val dateInstant = Instant.ofEpochSecond(info.date)
val dateTime = LocalDateTime.ofInstant(dateInstant, ZoneId.systemDefault())
val sunriseInstant = Instant.ofEpochSecond(info.sunrise)
Expand All @@ -43,7 +43,9 @@ class ForecastRecyclerViewAdapter(private val data: List<DayForecast>)
.load(iconURL)
.into(binding.forecastImage)


itemView.setOnClickListener{
itemClicked.onItemClicked(info)
}
}
}

Expand All @@ -55,7 +57,7 @@ class ForecastRecyclerViewAdapter(private val data: List<DayForecast>)

@RequiresApi(Build.VERSION_CODES.O)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(data[position])
holder.bind(data[position], itemClicked)
}

override fun getItemCount() = data.size
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/java/com/example/weatherapp/ForecastTemp.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.example.weatherapp

import android.os.Parcelable
import kotlinx.android.parcel.Parcelize

@Parcelize
class ForecastTemp (
val day: Float,
val min: Float,
val max:Float)
val max:Float) : Parcelable
5 changes: 5 additions & 0 deletions app/src/main/java/com/example/weatherapp/ItemClicked.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.weatherapp

interface ItemClicked {
fun onItemClicked(info: DayForecast)
}
3 changes: 0 additions & 3 deletions app/src/main/java/com/example/weatherapp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,4 @@ class MainActivity : AppCompatActivity() {
super.onResume()

}



}
Loading