- weathered
@@ -2,17 +2,20 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
|
||||
<application
|
||||
android:name="com.appttude.h_mal.atlas_weather.application.AppClass"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:node="merge">
|
||||
|
||||
<activity android:name=".ui.MainActivity"
|
||||
<activity android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
@@ -25,14 +28,10 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.settings.UnitSettingsActivity"
|
||||
android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.settings.UnitSettingsActivity"
|
||||
android:label="Settings" />
|
||||
|
||||
<receiver
|
||||
android:name=".notification.NotificationReceiver"
|
||||
android:parentActivityName=".MainActivity" />
|
||||
|
||||
<receiver android:name=".widget.NewAppWidget">
|
||||
<receiver android:name="com.appttude.h_mal.atlas_weather.monoWeather.widget.NewAppWidget">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
<action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
|
||||
@@ -46,8 +45,13 @@
|
||||
|
||||
|
||||
<service
|
||||
android:name=".widget.WidgetRemoteViewsService"
|
||||
android:name="com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetRemoteViewsService"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
|
||||
<service
|
||||
android:name="com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetJobServiceIntent"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
abstract class BaseActivity : AppCompatActivity(){
|
||||
|
||||
|
||||
}
|
||||
@@ -1,30 +1,48 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.appttude.h_mal.atlas_weather.utils.Event
|
||||
import com.appttude.h_mal.atlas_weather.utils.displayToast
|
||||
import com.appttude.h_mal.atlas_weather.utils.hide
|
||||
import com.appttude.h_mal.atlas_weather.utils.show
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.kodein.di.KodeinAware
|
||||
import org.kodein.di.android.x.kodein
|
||||
import org.kodein.di.generic.instance
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
abstract class BaseFragment: Fragment(){
|
||||
abstract class BaseFragment : Fragment(), KodeinAware {
|
||||
|
||||
override val kodein by kodein()
|
||||
val factory by instance<ApplicationViewModelFactory>()
|
||||
|
||||
inline fun <reified VM : ViewModel> getFragmentViewModel(): Lazy<VM> = viewModels { factory }
|
||||
|
||||
private var shortAnimationDuration by Delegates.notNull<Int>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
shortAnimationDuration = resources.getInteger(android.R.integer.config_shortAnimTime)
|
||||
}
|
||||
|
||||
// toggle visibility of progress spinner while async operations are taking place
|
||||
fun progressBarStateObserver(progressBar: View) = Observer<Event<Boolean>> {
|
||||
when(it.getContentIfNotHandled()){
|
||||
true -> {
|
||||
progressBar.show()
|
||||
}
|
||||
false -> {
|
||||
progressBar.hide()
|
||||
}
|
||||
when (it.getContentIfNotHandled()) {
|
||||
true -> progressBar.fadeIn()
|
||||
false -> progressBar.fadeOut()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,21 +53,70 @@ abstract class BaseFragment: Fragment(){
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun refreshObserver(refresher: SwipeRefreshLayout) = Observer<Event<Boolean>> {
|
||||
refresher.isRefreshing = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a permission for
|
||||
* @param permission with
|
||||
* @param permissionCode
|
||||
* Callback if is already permission granted
|
||||
* @param permissionGranted
|
||||
*/
|
||||
fun getPermissionResult(
|
||||
permission: String,
|
||||
permissionCode: Int,
|
||||
permissionGranted: () -> Unit
|
||||
){
|
||||
) {
|
||||
if (ActivityCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
requestPermissions(arrayOf(permission), permissionCode)
|
||||
return
|
||||
}else{
|
||||
CoroutineScope(Dispatchers.Main).launch{
|
||||
} else {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
permissionGranted.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun View.fadeIn() {
|
||||
apply {
|
||||
// Set the content view to 0% opacity but visible, so that it is visible
|
||||
// (but fully transparent) during the animation.
|
||||
alpha = 0f
|
||||
hide()
|
||||
|
||||
// Animate the content view to 100% opacity, and clear any animation
|
||||
// listener set on the view.
|
||||
animate()
|
||||
.alpha(1f)
|
||||
.setDuration(shortAnimationDuration.toLong())
|
||||
.setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun View.fadeOut() {
|
||||
apply {
|
||||
// Set the content view to 0% opacity but visible, so that it is visible
|
||||
// (but fully transparent) during the animation.
|
||||
alpha = 1f
|
||||
show()
|
||||
|
||||
// Animate the content view to 100% opacity, and clear any animation
|
||||
// listener set on the view.
|
||||
animate()
|
||||
.alpha(0f)
|
||||
.setDuration(shortAnimationDuration.toLong())
|
||||
.setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
hide()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui
|
||||
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
|
||||
class EmptyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
|
||||
val icon: ImageView = itemView.findViewById(R.id.icon)
|
||||
var bodyTV: TextView = itemView.findViewById(R.id.body_text)
|
||||
var headerTV: TextView = itemView.findViewById(R.id.header_text)
|
||||
|
||||
fun bindData(@DrawableRes imageRes: Int?,header: String, body: String){
|
||||
imageRes?.let { icon.setImageResource(it) }
|
||||
headerTV.text = header
|
||||
bodyTV.text = body
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
@@ -11,11 +12,10 @@ import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.settings.UnitSettingsActivity
|
||||
import com.appttude.h_mal.atlas_weather.utils.goBack
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import kotlinx.android.synthetic.main.activity_main_navigation.*
|
||||
|
||||
class MainActivity : BaseActivity() {
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
lateinit var navHost: NavHostFragment
|
||||
|
||||
@@ -32,10 +32,8 @@ class MainActivity : BaseActivity() {
|
||||
navController.setGraph(R.navigation.main_navigation)
|
||||
|
||||
setupBottomBar(navView, navController)
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun setupBottomBar(navView: BottomNavigationView, navController: NavController) {
|
||||
val tabs = setOf(R.id.nav_home, R.id.nav_world)
|
||||
val appBarConfiguration = AppBarConfiguration(tabs)
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui
|
||||
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.WeatherDisplay
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.WeatherRecyclerAdapter
|
||||
import com.appttude.h_mal.atlas_weather.utils.navigateTo
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel
|
||||
import kotlinx.android.synthetic.main.fragment_home.*
|
||||
import kotlinx.android.synthetic.main.fragment_main.*
|
||||
|
||||
|
||||
class WorldItemFragment : Fragment() {
|
||||
private var param1: WeatherDisplay? = null
|
||||
class WorldItemFragment : BaseFragment() {
|
||||
|
||||
private val viewModel by getFragmentViewModel<WorldViewModel>()
|
||||
private var param1: String? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
param1 = WorldItemFragmentArgs.fromBundle(requireArguments()).weatherDisplay
|
||||
param1 = WorldItemFragmentArgs.fromBundle(requireArguments()).locationName
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
@@ -37,13 +39,30 @@ class WorldItemFragment : Fragment() {
|
||||
navigateTo(directions)
|
||||
}
|
||||
|
||||
param1?.let { recyclerAdapter.addCurrent(it) }
|
||||
param1?.let { viewModel.getSingleLocation(it) }
|
||||
|
||||
viewModel.singleWeatherLiveData.observe(viewLifecycleOwner, Observer {
|
||||
recyclerAdapter.addCurrent(it)
|
||||
swipe_refresh.isRefreshing = false
|
||||
})
|
||||
|
||||
forecast_listview.apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = recyclerAdapter
|
||||
}
|
||||
|
||||
swipe_refresh.apply {
|
||||
setOnRefreshListener {
|
||||
param1?.let {
|
||||
viewModel.fetchDataForSingleLocation(it)
|
||||
isRefreshing = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.operationState.observe(viewLifecycleOwner, progressBarStateObserver(progressBar))
|
||||
viewModel.operationError.observe(viewLifecycleOwner, errorObserver())
|
||||
viewModel.operationRefresh.observe(viewLifecycleOwner, refreshObserver(swipe_refresh))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,14 +32,21 @@ class FurtherInfoFragment : Fragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
maxtemp.text = param1?.mainTemp
|
||||
averagetemp.text = param1?.averageTemp
|
||||
minimumtemp.text = param1?.minorTemp
|
||||
windtext.text = param1?.windText
|
||||
preciptext.text = param1?.precipitation
|
||||
humiditytext.text = param1?.humidity
|
||||
maxtemp.text = param1?.mainTemp.appendWith(requireContext().getString(R.string.degrees))
|
||||
averagetemp.text = param1?.averageTemp.appendWith(requireContext().getString(R.string.degrees))
|
||||
minimumtemp.text = param1?.minorTemp.appendWith(requireContext().getString(R.string.degrees))
|
||||
windtext.text = param1?.windText.appendWith(" km")
|
||||
preciptext.text = param1?.precipitation.appendWith(" %")
|
||||
cloudtext.text = param1?.cloud.appendWith(" %")
|
||||
humiditytext.text = param1?.humidity.appendWith(" %")
|
||||
uvtext.text = param1?.uvi
|
||||
sunrisetext.text = param1?.sunrise
|
||||
sunsettext.text = param1?.sunset
|
||||
}
|
||||
|
||||
fun String?.appendWith(suffix: String): String?{
|
||||
return this?.let {
|
||||
StringBuilder().append(it).append(suffix).toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,43 +8,32 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.observe
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.application.LOCATION_PERMISSION_REQUEST
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.BaseFragment
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.WeatherRecyclerAdapter
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.home.HomeFragmentDirections
|
||||
import com.appttude.h_mal.atlas_weather.utils.displayToast
|
||||
import com.appttude.h_mal.atlas_weather.utils.navigateTo
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.MainViewModel
|
||||
import kotlinx.android.synthetic.main.activity_add_forecast.*
|
||||
import kotlinx.android.synthetic.main.activity_add_forecast.progressBar
|
||||
import kotlinx.android.synthetic.main.fragment_home.*
|
||||
import kotlinx.android.synthetic.main.fragment_main.*
|
||||
import org.kodein.di.KodeinAware
|
||||
import org.kodein.di.android.x.kodein
|
||||
import org.kodein.di.generic.instance
|
||||
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class HomeFragment : BaseFragment(), KodeinAware {
|
||||
override val kodein by kodein()
|
||||
private val factory by instance<ApplicationViewModelFactory>()
|
||||
class HomeFragment : BaseFragment(){
|
||||
|
||||
private val viewModel by activityViewModels<MainViewModel> { factory }
|
||||
private val viewModel by getFragmentViewModel<MainViewModel>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_home, container, false)
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
@@ -60,16 +49,16 @@ class HomeFragment : BaseFragment(), KodeinAware {
|
||||
adapter = recyclerAdapter
|
||||
}
|
||||
|
||||
getPermissionResult(Manifest.permission.ACCESS_FINE_LOCATION, LOCATION_PERMISSION_REQUEST){
|
||||
getPermissionResult(Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST){
|
||||
viewModel.fetchData()
|
||||
}
|
||||
|
||||
swipe_refresh.apply {
|
||||
setOnRefreshListener {
|
||||
getPermissionResult(Manifest.permission.ACCESS_FINE_LOCATION, LOCATION_PERMISSION_REQUEST){
|
||||
getPermissionResult(Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST){
|
||||
viewModel.fetchData()
|
||||
isRefreshing = true
|
||||
}
|
||||
isRefreshing = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,11 +68,7 @@ class HomeFragment : BaseFragment(), KodeinAware {
|
||||
|
||||
viewModel.operationState.observe(viewLifecycleOwner, progressBarStateObserver(progressBar))
|
||||
viewModel.operationError.observe(viewLifecycleOwner, errorObserver())
|
||||
|
||||
viewModel.operationState.observe(viewLifecycleOwner){
|
||||
swipe_refresh.isRefreshing = false
|
||||
}
|
||||
|
||||
viewModel.operationRefresh.observe(viewLifecycleOwner, refreshObserver(swipe_refresh))
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
class EmptyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
|
||||
@@ -17,9 +17,9 @@ class ViewHolderCurrent(listItemView: View) : RecyclerView.ViewHolder(listItemVi
|
||||
var tempUnit: TextView = listItemView.findViewById(R.id.temp_unit_4)
|
||||
|
||||
fun bindData(weather: WeatherDisplay?){
|
||||
locationTV.text = weather?.location
|
||||
locationTV.text = weather?.displayName
|
||||
conditionTV.text = weather?.description
|
||||
weatherIV.loadImage(weather?.iconURL, 64, 64)
|
||||
weatherIV.loadImage(weather?.iconURL)
|
||||
avgTempTV.text = weather?.averageTemp?.toInt().toString()
|
||||
tempUnit.text = weather?.unit
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.Forecast
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.WeatherDisplay
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.EmptyViewHolder
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.forecast.ViewHolderForecast
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.forecastDaily.ViewHolderForecastDaily
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.further.ViewHolderFurtherDetails
|
||||
@@ -24,16 +24,16 @@ class WeatherRecyclerAdapter(
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (getDataType(viewType)){
|
||||
is ViewType.Empty -> {
|
||||
val emptyViewHolder = View(parent.context)
|
||||
val emptyViewHolder = parent.generateView(R.layout.empty_state_layout)
|
||||
EmptyViewHolder(emptyViewHolder)
|
||||
}
|
||||
is ViewType.Current -> {
|
||||
val viewCurrent = parent.generateView(R.layout.mono_item_one)
|
||||
ViewHolderCurrent(viewCurrent)
|
||||
}
|
||||
is ViewType.Forecast -> {
|
||||
is ViewType.ForecastHourly -> {
|
||||
val viewForecast = parent.generateView(R.layout.mono_item_forecast)
|
||||
ViewHolderForecast(viewForecast, itemClick)
|
||||
ViewHolderForecast(viewForecast)
|
||||
}
|
||||
is ViewType.Further -> {
|
||||
val viewFurther = parent.generateView(R.layout.mono_item_two)
|
||||
@@ -49,7 +49,7 @@ class WeatherRecyclerAdapter(
|
||||
sealed class ViewType{
|
||||
object Empty : ViewType()
|
||||
object Current : ViewType()
|
||||
object Forecast : ViewType()
|
||||
object ForecastHourly : ViewType()
|
||||
object ForecastDaily : ViewType()
|
||||
object Further : ViewType()
|
||||
}
|
||||
@@ -58,7 +58,7 @@ class WeatherRecyclerAdapter(
|
||||
return when (type){
|
||||
0 -> ViewType.Empty
|
||||
1 -> ViewType.Current
|
||||
2 -> ViewType.Forecast
|
||||
2 -> ViewType.ForecastHourly
|
||||
3 -> ViewType.Further
|
||||
4 -> ViewType.ForecastDaily
|
||||
else -> ViewType.Empty
|
||||
@@ -71,7 +71,7 @@ class WeatherRecyclerAdapter(
|
||||
0 -> 1
|
||||
1 -> 3
|
||||
2 -> 2
|
||||
in 3 until (itemCount - 1) -> 4
|
||||
in 3 until (itemCount) -> 4
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,6 @@ class WeatherRecyclerAdapter(
|
||||
when (getDataType(getItemViewType(position))){
|
||||
is ViewType.Empty -> {
|
||||
holder as EmptyViewHolder
|
||||
|
||||
}
|
||||
is ViewType.Current -> {
|
||||
val viewHolderCurrent = holder as ViewHolderCurrent
|
||||
@@ -90,14 +89,17 @@ class WeatherRecyclerAdapter(
|
||||
val viewHolderCurrent = holder as ViewHolderFurtherDetails
|
||||
viewHolderCurrent.bindData(weather)
|
||||
}
|
||||
is ViewType.Forecast -> {
|
||||
is ViewType.ForecastHourly -> {
|
||||
val viewHolderForecast = holder as ViewHolderForecast
|
||||
viewHolderForecast.bindView(weather?.forecast)
|
||||
viewHolderForecast.bindView(weather?.hourly)
|
||||
}
|
||||
is ViewType.ForecastDaily -> {
|
||||
val viewHolderForecast = holder as ViewHolderForecastDaily
|
||||
weather?.forecast?.getOrNull(position -3)?.let {
|
||||
viewHolderForecast.bindView(it)
|
||||
weather?.forecast?.getOrNull(position - 3)?.let { f ->
|
||||
viewHolderForecast.bindView(f)
|
||||
viewHolderForecast.itemView.setOnClickListener {
|
||||
itemClick.invoke(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,8 +107,7 @@ class WeatherRecyclerAdapter(
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
if (weather == null) return 0
|
||||
return 3 + (weather?.forecast?.size ?: 0)
|
||||
return if (weather == null) 0 else 3 + (weather?.forecast?.size ?: 0)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,20 +5,19 @@ import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.Forecast
|
||||
import com.appttude.h_mal.atlas_weather.model.weather.Hour
|
||||
import com.appttude.h_mal.atlas_weather.utils.loadImage
|
||||
import com.appttude.h_mal.atlas_weather.utils.toTime
|
||||
|
||||
class GridCellHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
var dayTV: TextView = itemView.findViewById(R.id.widget_item_day)
|
||||
var weatherIV: ImageView = itemView.findViewById(R.id.widget_item_image)
|
||||
var mainTempTV: TextView = itemView.findViewById(R.id.widget_item_temp_high)
|
||||
var lowTempTV: TextView = itemView.findViewById(R.id.widget_item_temp_low)
|
||||
|
||||
fun bindView(forecast: Forecast?) {
|
||||
dayTV.text = forecast?.date
|
||||
weatherIV.loadImage(forecast?.weatherIcon, 64, 64)
|
||||
mainTempTV.text = forecast?.mainTemp
|
||||
lowTempTV.text = forecast?.minorTemp
|
||||
fun bindView(hour: Hour?) {
|
||||
dayTV.text = hour?.dt?.toTime()
|
||||
weatherIV.loadImage(hour?.icon)
|
||||
mainTempTV.text = hour?.temp?.toInt()?.toString()
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,13 @@ package com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.forecast
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.Forecast
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.WeatherDisplay
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.ViewHolderCurrent
|
||||
import com.appttude.h_mal.atlas_weather.model.weather.Hour
|
||||
import com.appttude.h_mal.atlas_weather.utils.generateView
|
||||
|
||||
class GridForecastAdapter(
|
||||
val itemClick: (Forecast) -> Unit
|
||||
): RecyclerView.Adapter<RecyclerView.ViewHolder>(){
|
||||
var weather: MutableList<Forecast> = mutableListOf()
|
||||
class GridForecastAdapter(): RecyclerView.Adapter<RecyclerView.ViewHolder>(){
|
||||
var weather: MutableList<Hour> = mutableListOf()
|
||||
|
||||
fun addCurrent(current: List<Forecast>?){
|
||||
fun addCurrent(current: List<Hour>?){
|
||||
weather.clear()
|
||||
current?.let { weather.addAll(it) }
|
||||
notifyDataSetChanged()
|
||||
@@ -28,9 +24,6 @@ class GridForecastAdapter(
|
||||
val view = holder as GridCellHolder
|
||||
val forecast = weather[position]
|
||||
view.bindView(forecast)
|
||||
view.itemView.setOnClickListener {
|
||||
itemClick.invoke(forecast)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = weather.size
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.forecast
|
||||
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.Forecast
|
||||
import com.appttude.h_mal.atlas_weather.utils.loadImage
|
||||
import com.appttude.h_mal.atlas_weather.model.weather.Hour
|
||||
|
||||
class ViewHolderForecast(
|
||||
itemView: View,
|
||||
private val itemClick: (Forecast) -> Unit
|
||||
itemView: View
|
||||
) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
var recyclerView: RecyclerView = itemView.findViewById(R.id.forecast_recyclerview)
|
||||
|
||||
fun bindView(forecasts: List<Forecast>?) {
|
||||
val adapter = GridForecastAdapter(itemClick)
|
||||
fun bindView(forecasts: List<Hour>?) {
|
||||
val adapter = GridForecastAdapter()
|
||||
adapter.addCurrent(forecasts)
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
|
||||
@@ -11,14 +11,16 @@ import com.appttude.h_mal.atlas_weather.utils.loadImage
|
||||
class ViewHolderForecastDaily(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
var dateTV: TextView = itemView.findViewById(R.id.list_date)
|
||||
var dayTV: TextView = itemView.findViewById(R.id.list_day)
|
||||
var weatherIV: ImageView = itemView.findViewById(R.id.list_icon)
|
||||
var mainTempTV: TextView = itemView.findViewById(R.id.list_main_temp)
|
||||
var dayTV: TextView = itemView.findViewById(R.id.db_condition)
|
||||
var weatherIV: ImageView = itemView.findViewById(R.id.db_icon)
|
||||
var mainTempTV: TextView = itemView.findViewById(R.id.db_main_temp)
|
||||
var tempUnits: TextView = itemView.findViewById(R.id.db_temp_unit)
|
||||
|
||||
fun bindView(forecast: Forecast?) {
|
||||
dateTV.text = forecast?.date
|
||||
dayTV.text = forecast?.day
|
||||
weatherIV.loadImage(forecast?.weatherIcon, 64, 64)
|
||||
weatherIV.loadImage(forecast?.weatherIcon)
|
||||
mainTempTV.text = forecast?.mainTemp
|
||||
tempUnits.text = itemView.context.getString(R.string.degrees)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui.settings
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||
import android.os.Bundle
|
||||
@@ -13,7 +10,6 @@ import android.preference.PreferenceFragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.widget.NewAppWidget
|
||||
import java.util.*
|
||||
|
||||
|
||||
class UnitSettingsActivity : PreferenceActivity() {
|
||||
@@ -33,9 +29,6 @@ class UnitSettingsActivity : PreferenceActivity() {
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
// if (key == "notif_boolean") {
|
||||
// setupNotificationBroadcaster(baseContext)
|
||||
// }
|
||||
|
||||
if (key == "widget_black_background"){
|
||||
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
|
||||
@@ -49,34 +42,7 @@ class UnitSettingsActivity : PreferenceActivity() {
|
||||
prefs.registerOnSharedPreferenceChangeListener(prefListener)
|
||||
}
|
||||
|
||||
// fun setupNotificationBroadcaster(context: Context) {
|
||||
// val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
// val notificationIntent = Intent(context, NotificationReceiver::class.java)
|
||||
// val broadcast = PendingIntent.getBroadcast(context, 100, notificationIntent,
|
||||
// PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
// val cal: Calendar = Calendar.getInstance()
|
||||
// cal.set(Calendar.HOUR_OF_DAY, 6)
|
||||
// cal.set(Calendar.MINUTE, 8)
|
||||
// cal.set(Calendar.SECOND, 5)
|
||||
// alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.timeInMillis, AlarmManager.INTERVAL_DAY, broadcast)
|
||||
// }
|
||||
|
||||
override fun onBackPressed() {
|
||||
super.onBackPressed()
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
|
||||
// Log.i(TAG, "onSharedPreferenceChanged: " + s);
|
||||
// if (s == "temp_units"){
|
||||
// Intent intent = new Intent(getBaseContext(), NewAppWidget.class);
|
||||
// intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
||||
//
|
||||
// int[] ids = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), NewAppWidget.class));
|
||||
// intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
|
||||
// sendBroadcast(intent);
|
||||
// }
|
||||
// }
|
||||
class MyPreferenceFragment : PreferenceFragment() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -4,25 +4,19 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.observe
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.BaseFragment
|
||||
import com.appttude.h_mal.atlas_weather.utils.displayToast
|
||||
import com.appttude.h_mal.atlas_weather.utils.goBack
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory
|
||||
import com.appttude.h_mal.atlas_weather.utils.hideKeyboard
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel
|
||||
import kotlinx.android.synthetic.main.activity_add_forecast.*
|
||||
import org.kodein.di.KodeinAware
|
||||
import org.kodein.di.android.x.kodein
|
||||
import org.kodein.di.generic.instance
|
||||
|
||||
|
||||
class AddLocationFragment : BaseFragment(), KodeinAware {
|
||||
override val kodein by kodein()
|
||||
private val factory by instance<ApplicationViewModelFactory>()
|
||||
class AddLocationFragment : BaseFragment() {
|
||||
|
||||
private val viewModel by viewModels<WorldViewModel> { factory }
|
||||
private val viewModel by getFragmentViewModel<WorldViewModel>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
@@ -39,18 +33,19 @@ class AddLocationFragment : BaseFragment(), KodeinAware {
|
||||
location_name_tv.error = "Location cannot be blank"
|
||||
return@setOnClickListener
|
||||
}
|
||||
viewModel.fetchDataForSingleLocation(locationName)
|
||||
viewModel.fetchDataForSingleLocationSearch(locationName)
|
||||
hideKeyboard()
|
||||
}
|
||||
|
||||
viewModel.operationState.observe(viewLifecycleOwner, progressBarStateObserver(progressBar))
|
||||
viewModel.operationError.observe(viewLifecycleOwner, errorObserver())
|
||||
|
||||
viewModel.operationComplete.observe(viewLifecycleOwner) {
|
||||
it?.getContentIfNotHandled()?.let {message ->
|
||||
it?.getContentIfNotHandled()?.let { message ->
|
||||
displayToast(message)
|
||||
}
|
||||
goBack()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +1,36 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui.world
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.observe
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.BaseFragment
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.world.WorldFragmentDirections
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.WorldItemFragmentDirections
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.world.WorldFragmentDirections.actionWorldFragmentToWorldItemFragment
|
||||
import com.appttude.h_mal.atlas_weather.utils.navigateTo
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.android.synthetic.main.fragment_add_location.*
|
||||
import org.kodein.di.KodeinAware
|
||||
import org.kodein.di.android.x.kodein
|
||||
import org.kodein.di.generic.instance
|
||||
import kotlinx.android.synthetic.main.fragment__two.*
|
||||
import kotlinx.android.synthetic.main.fragment_add_location.floatingActionButton
|
||||
import kotlinx.android.synthetic.main.fragment_add_location.world_recycler
|
||||
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class WorldFragment : BaseFragment(), KodeinAware {
|
||||
override val kodein by kodein()
|
||||
private val factory by instance<ApplicationViewModelFactory>()
|
||||
class WorldFragment : BaseFragment() {
|
||||
private val viewModel by getFragmentViewModel<WorldViewModel>()
|
||||
|
||||
val viewModel by viewModels<WorldViewModel> { factory }
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
viewModel.fetchAllLocations()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
@@ -44,7 +43,7 @@ class WorldFragment : BaseFragment(), KodeinAware {
|
||||
|
||||
val recyclerAdapter = WorldRecyclerAdapter({
|
||||
val direction =
|
||||
WorldFragmentDirections.actionWorldFragmentToWorldItemFragment(it)
|
||||
actionWorldFragmentToWorldItemFragment(it.location)
|
||||
navigateTo(direction)
|
||||
}){
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
@@ -71,15 +70,9 @@ class WorldFragment : BaseFragment(), KodeinAware {
|
||||
navigateTo(R.id.action_worldFragment_to_addLocationFragment)
|
||||
}
|
||||
|
||||
viewModel.operationState.observe(viewLifecycleOwner, progressBarStateObserver(progressBar2))
|
||||
viewModel.operationState.observe(viewLifecycleOwner, progressBarStateObserver(progressBar))
|
||||
viewModel.operationError.observe(viewLifecycleOwner, errorObserver())
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
viewModel.fetchAllLocations()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.WeatherDisplay
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.EmptyViewHolder
|
||||
import com.appttude.h_mal.atlas_weather.utils.generateView
|
||||
import com.appttude.h_mal.atlas_weather.utils.loadImage
|
||||
|
||||
@@ -25,7 +26,7 @@ class WorldRecyclerAdapter(
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (getDataType(viewType)){
|
||||
is ViewType.Empty -> {
|
||||
val emptyViewHolder = View(parent.context)
|
||||
val emptyViewHolder = parent.generateView(R.layout.empty_state_layout)
|
||||
EmptyViewHolder(emptyViewHolder)
|
||||
}
|
||||
is ViewType.Current -> {
|
||||
@@ -56,7 +57,7 @@ class WorldRecyclerAdapter(
|
||||
when (getDataType(getItemViewType(position))){
|
||||
is ViewType.Empty -> {
|
||||
holder as EmptyViewHolder
|
||||
|
||||
holder.bindData(null, "World List Empty", "Please add a location")
|
||||
}
|
||||
is ViewType.Current -> {
|
||||
val viewHolderCurrent = holder as WorldHolderCurrent
|
||||
@@ -83,20 +84,17 @@ class WorldRecyclerAdapter(
|
||||
var conditionTV: TextView = listItemView.findViewById(R.id.db_condition)
|
||||
var weatherIV: ImageView = listItemView.findViewById(R.id.db_icon)
|
||||
var avgTempTV: TextView = listItemView.findViewById(R.id.db_main_temp)
|
||||
var tempUnit: TextView = listItemView.findViewById(R.id.db_minor_temp)
|
||||
var tempUnit: TextView = listItemView.findViewById(R.id.db_temp_unit)
|
||||
|
||||
fun bindData(weather: WeatherDisplay?){
|
||||
locationTV.text = weather?.location
|
||||
locationTV.text = weather?.displayName
|
||||
conditionTV.text = weather?.description
|
||||
weatherIV.loadImage(weather?.iconURL, 64, 64)
|
||||
weatherIV.loadImage(weather?.iconURL)
|
||||
avgTempTV.text = weather?.forecast?.get(0)?.mainTemp
|
||||
tempUnit.text = weather?.unit
|
||||
tempUnit.text = itemView.context.getString(R.string.degrees)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal class EmptyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
|
||||
|
||||
}
|
||||
@@ -9,16 +9,33 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.RemoteViews
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.core.app.JobIntentService
|
||||
import com.appttude.h_mal.atlas_weather.helper.ServicesHelper
|
||||
import org.kodein.di.KodeinAware
|
||||
import org.kodein.di.LateInitKodein
|
||||
import org.kodein.di.generic.instance
|
||||
|
||||
abstract class BaseWidgetClass : AppWidgetProvider(){
|
||||
abstract class BaseWidgetServiceIntentClass : JobIntentService(){
|
||||
|
||||
private val kodein = LateInitKodein()
|
||||
val helper: ServicesHelper by kodein.instance()
|
||||
|
||||
fun setKodein(context: Context){
|
||||
kodein.baseKodein = (context.applicationContext as KodeinAware).kodein
|
||||
}
|
||||
|
||||
fun createRemoteView(context: Context, @LayoutRes id: Int): RemoteViews {
|
||||
return RemoteViews(context.packageName, id)
|
||||
}
|
||||
|
||||
fun AppWidgetProvider.createUpdatePendingIntent(context: Context, appWidgetId: Int): PendingIntent? {
|
||||
// Create pending intent commonly used for 'click to update' features
|
||||
fun <T: AppWidgetProvider> createUpdatePendingIntent(
|
||||
appWidgetProvider: Class<T>,
|
||||
context: Context,
|
||||
appWidgetId: Int
|
||||
): PendingIntent? {
|
||||
val seconds = (System.currentTimeMillis() / 1000L).toInt()
|
||||
val intentUpdate = Intent(context, this::class.java)
|
||||
val intentUpdate = Intent(context.applicationContext, appWidgetProvider)
|
||||
intentUpdate.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||
val idArray = intArrayOf(appWidgetId)
|
||||
intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray)
|
||||
@@ -27,6 +44,10 @@ abstract class BaseWidgetClass : AppWidgetProvider(){
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
/**
|
||||
* create a pending intent used to navigate to activity:
|
||||
* @param activityClass
|
||||
*/
|
||||
fun <T: Activity> createClickingPendingIntent(context: Context, activityClass: Class<T>): PendingIntent {
|
||||
val clickIntentTemplate = Intent(context, activityClass)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.widget
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import android.widget.RemoteViews
|
||||
import android.widget.RemoteViewsService.RemoteViewsFactory
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
@@ -11,29 +9,20 @@ import com.appttude.h_mal.atlas_weather.helper.ServicesHelper
|
||||
import com.appttude.h_mal.atlas_weather.model.widget.InnerWidgetData
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.kodein.di.KodeinAware
|
||||
import org.kodein.di.LateInitKodein
|
||||
import org.kodein.di.android.kodein
|
||||
import org.kodein.di.generic.instance
|
||||
|
||||
|
||||
class MyWidgetRemoteViewsFactory(
|
||||
private val context: Context,
|
||||
val intent: Intent
|
||||
) : RemoteViewsFactory{
|
||||
private val TAG = "MyWidgetRemoteViewsFactory"
|
||||
) : RemoteViewsFactory, KodeinAware{
|
||||
|
||||
private val kodein = LateInitKodein()
|
||||
override val kodein by kodein(context)
|
||||
private val helper : ServicesHelper by kodein.instance()
|
||||
|
||||
private var appWidgetId: Int? = 0
|
||||
private var list: List<InnerWidgetData>? = null
|
||||
|
||||
init {
|
||||
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID)
|
||||
kodein.baseKodein = (context.applicationContext as KodeinAware).kodein
|
||||
|
||||
}
|
||||
|
||||
override fun onCreate() {}
|
||||
override fun onDataSetChanged() {
|
||||
runBlocking {
|
||||
@@ -49,7 +38,6 @@ class MyWidgetRemoteViewsFactory(
|
||||
|
||||
if (list.isNullOrEmpty()) return rv
|
||||
|
||||
|
||||
list?.get(i)?.let {
|
||||
rv.setTextViewText(R.id.widget_item_day, it.date)
|
||||
rv.setImageViewBitmap(R.id.widget_item_image, it.icon)
|
||||
@@ -64,15 +52,9 @@ class MyWidgetRemoteViewsFactory(
|
||||
return RemoteViews(context.packageName, R.layout.widget_item_loading)
|
||||
}
|
||||
|
||||
override fun getViewTypeCount(): Int = 1
|
||||
|
||||
override fun getViewTypeCount(): Int = 2
|
||||
|
||||
override fun getItemId(i: Int): Long = i.toLong()
|
||||
|
||||
|
||||
override fun hasStableIds(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
override fun hasStableIds(): Boolean = true
|
||||
}
|
||||
@@ -1,141 +1,32 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.widget
|
||||
|
||||
import android.Manifest
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.app.ActivityCompat
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.helper.ServicesHelper
|
||||
import com.appttude.h_mal.atlas_weather.model.widget.WidgetData
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.MainActivity
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.kodein.di.KodeinAware
|
||||
import org.kodein.di.LateInitKodein
|
||||
import org.kodein.di.generic.instance
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetJobServiceIntent.Companion.enqueueWork
|
||||
|
||||
/**
|
||||
* Implementation of App Widget functionality.
|
||||
*/
|
||||
private val TAG = NewAppWidget::class.java.simpleName
|
||||
class NewAppWidget : BaseWidgetClass() {
|
||||
|
||||
private val kodein = LateInitKodein()
|
||||
private val helper : ServicesHelper by kodein.instance()
|
||||
class NewAppWidget : AppWidgetProvider() {
|
||||
|
||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||
kodein.baseKodein = (context.applicationContext as KodeinAware).kodein
|
||||
// There may be multiple widgets active, so update all of them
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
return
|
||||
}
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val results = helper.fetchData()
|
||||
if (results) return@launch
|
||||
val weatherWidgetCurrent = helper.getWidgetWeather()
|
||||
|
||||
withContext(Dispatchers.Main){
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
val updatePendingIntent = createUpdatePendingIntent(context, appWidgetId)
|
||||
val views = createRemoteView(context, R.layout.new_app_widget)
|
||||
bindView(context, appWidgetId, views, updatePendingIntent, weatherWidgetCurrent)
|
||||
}
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
}
|
||||
|
||||
}
|
||||
loadWidget(context)
|
||||
}
|
||||
|
||||
override fun onEnabled(context: Context) {
|
||||
try {
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
val thisAppWidget = ComponentName(context.packageName, NewAppWidget::class.java.name)
|
||||
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
|
||||
onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_listview)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "onEnabled: ", e)
|
||||
}
|
||||
super.onEnabled(context)
|
||||
|
||||
loadWidget(context)
|
||||
}
|
||||
|
||||
override fun onDisabled(context: Context) {
|
||||
// Enter relevant functionality for when the last widget is disabled
|
||||
}
|
||||
override fun onDisabled(context: Context) { }
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action ==
|
||||
AppWidgetManager.ACTION_APPWIDGET_UPDATE) {
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
val thisAppWidget = ComponentName(context.packageName, NewAppWidget::class.java.name)
|
||||
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_listview)
|
||||
}
|
||||
super.onReceive(context, intent)
|
||||
}
|
||||
|
||||
private fun createForecastListIntent(
|
||||
context: Context,
|
||||
appWidgetId: Int
|
||||
): Intent {
|
||||
return Intent(context, WidgetRemoteViewsService::class.java).apply {
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindView(
|
||||
context: Context,
|
||||
appWidgetId: Int,
|
||||
views: RemoteViews,
|
||||
updatePendingIntent: PendingIntent?,
|
||||
weather: WidgetData?){
|
||||
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
|
||||
views.setInt(R.id.whole_widget_view, "setBackgroundColor", helper.getWidgetBackground())
|
||||
|
||||
weather?.let {
|
||||
|
||||
val intent = createForecastListIntent(
|
||||
context,
|
||||
appWidgetId
|
||||
)
|
||||
|
||||
views.setRemoteAdapter(R.id.widget_listview, intent)
|
||||
views.setTextViewText(R.id.widget_main_temp, it.currentTemp)
|
||||
views.setTextViewText(R.id.widget_feel_temp, "°C")
|
||||
views.setTextViewText(R.id.widget_current_location, it.location)
|
||||
views.setImageViewResource(R.id.location_icon, R.drawable.location_flag)
|
||||
views.setImageViewBitmap(R.id.widget_current_icon, it.icon)
|
||||
|
||||
val clickPendingIntentTemplate = createClickingPendingIntent(context, MainActivity::class.java)
|
||||
views.setPendingIntentTemplate(R.id.widget_listview, clickPendingIntentTemplate)
|
||||
|
||||
views.setOnClickPendingIntent(R.id.widget_current_icon, updatePendingIntent)
|
||||
views.setOnClickPendingIntent(R.id.widget_current_location, updatePendingIntent)
|
||||
|
||||
// Instruct the widget manager to update the widget
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
|
||||
return
|
||||
}
|
||||
|
||||
Log.i(TAG, "onPostExecute: weather is empty")
|
||||
views.setTextViewText(R.id.widget_current_location, "Refresh")
|
||||
views.setImageViewResource(R.id.widget_current_icon, R.drawable.widget_error_icon)
|
||||
views.setImageViewResource(R.id.location_icon, R.drawable.refreshing)
|
||||
views.setOnClickPendingIntent(R.id.widget_current_icon, updatePendingIntent)
|
||||
views.setOnClickPendingIntent(R.id.widget_current_location, updatePendingIntent)
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
private fun loadWidget(context: Context){
|
||||
val mIntent = Intent(context, WidgetJobServiceIntent::class.java)
|
||||
enqueueWork(context, mIntent)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.widget
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.app.ActivityCompat
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.widget.WidgetData
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.MainActivity
|
||||
import com.appttude.h_mal.atlas_weather.utils.isInternetAvailable
|
||||
import com.appttude.h_mal.atlas_weather.utils.tryOrNullSuspended
|
||||
import com.squareup.picasso.Picasso
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
|
||||
/**
|
||||
* Example implementation of a JobIntentService.
|
||||
*/
|
||||
class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() {
|
||||
|
||||
override fun onHandleWork(intent: Intent) {
|
||||
setKodein(this)
|
||||
// We have received work to do. The system or framework is already
|
||||
// holding a wake lock for us at this point, so we can just go.
|
||||
val appWidgetManager = AppWidgetManager.getInstance(this)
|
||||
val thisAppWidget = ComponentName(packageName, NewAppWidget::class.java.name)
|
||||
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||
!= PackageManager.PERMISSION_GRANTED || !isInternetAvailable(this.applicationContext)) {
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
setEmptyView(this, appWidgetManager, appWidgetId)
|
||||
}
|
||||
}else{
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val result = getWidgetWeather()
|
||||
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
bindView(this@WidgetJobServiceIntent, appWidgetManager, appWidgetId, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createForecastListIntent(
|
||||
context: Context,
|
||||
appWidgetId: Int
|
||||
): Intent {
|
||||
return Intent(context, WidgetRemoteViewsService::class.java).apply {
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
suspend fun getWidgetWeather(): WidgetData? {
|
||||
return tryOrNullSuspended {
|
||||
helper.fetchData()
|
||||
helper.getWidgetWeather()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setEmptyView(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
|
||||
try {
|
||||
val error = if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
"No Permission"
|
||||
} else if (!isInternetAvailable(context.applicationContext)) {
|
||||
"No Connection"
|
||||
} else {
|
||||
"No Data"
|
||||
}
|
||||
val updatePendingIntent = createUpdatePendingIntent(NewAppWidget::class.java, context, appWidgetId)
|
||||
val views = createRemoteView(context, R.layout.weather_app_widget)
|
||||
bindEmptyView(appWidgetManager, appWidgetId, views, updatePendingIntent, error)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun bindEmptyView(
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetId: Int,
|
||||
views: RemoteViews,
|
||||
clickingUpdateIntent: PendingIntent?,
|
||||
warning: String
|
||||
) {
|
||||
setLastUpdated(views)
|
||||
views.setTextViewText(R.id.widget_current_location, warning)
|
||||
views.setImageViewResource(R.id.widget_current_icon, R.drawable.ic_baseline_cloud_off_24)
|
||||
views.setImageViewResource(R.id.location_icon, 0)
|
||||
|
||||
views.setTextViewText(R.id.widget_main_temp, "")
|
||||
views.setTextViewText(R.id.widget_feel_temp, "")
|
||||
|
||||
views.setOnClickPendingIntent(R.id.widget_current_icon, clickingUpdateIntent)
|
||||
views.setOnClickPendingIntent(R.id.widget_current_location, clickingUpdateIntent)
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
|
||||
}
|
||||
|
||||
private fun bindView(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetId: Int,
|
||||
weather: WidgetData?) {
|
||||
val views = createRemoteView(context, R.layout.weather_app_widget)
|
||||
setLastUpdated(views)
|
||||
views.setInt(R.id.whole_widget_view, "setBackgroundColor", helper.getWidgetBackground())
|
||||
val clickingUpdatePendingIntent = createUpdatePendingIntent(NewAppWidget::class.java, context, appWidgetId)
|
||||
val forecastListIntent = createForecastListIntent(context, appWidgetId)
|
||||
|
||||
if (weather != null) {
|
||||
val clickPendingIntentTemplate =
|
||||
createClickingPendingIntent(context, MainActivity::class.java)
|
||||
|
||||
views.apply {
|
||||
setTextViewText(R.id.widget_main_temp, weather.currentTemp)
|
||||
setTextViewText(R.id.widget_feel_temp, "°C")
|
||||
setTextViewText(R.id.widget_current_location, weather.location)
|
||||
setImageViewResource(R.id.location_icon, R.drawable.location_flag)
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
Picasso.get().load(weather.icon).into(views, R.id.widget_current_icon, intArrayOf(appWidgetId))
|
||||
}
|
||||
setPendingIntentTemplate(R.id.widget_listview, clickPendingIntentTemplate)
|
||||
setOnClickPendingIntent(R.id.widget_current_icon, clickingUpdatePendingIntent)
|
||||
setOnClickPendingIntent(R.id.widget_current_location, clickingUpdatePendingIntent)
|
||||
|
||||
setRemoteAdapter(R.id.widget_listview, forecastListIntent)
|
||||
}
|
||||
|
||||
// Instruct the widget manager to update the widget
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
|
||||
} else {
|
||||
bindEmptyView(appWidgetManager, appWidgetId, views, clickingUpdatePendingIntent, "No Connection")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setLastUpdated(views: RemoteViews){
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
val current = LocalDateTime.now()
|
||||
val formatter = DateTimeFormatter.ofPattern("HH:mm")
|
||||
val formatted = current.format(formatter)
|
||||
views.setTextViewText(R.id.widget_current_status, "last updated: $formatted")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Unique job ID for this service.
|
||||
*/
|
||||
private const val JOB_ID = 1000
|
||||
|
||||
/**
|
||||
* Convenience method for enqueuing work in to this service.
|
||||
*/
|
||||
fun enqueueWork(context: Context, work: Intent) {
|
||||
enqueueWork(context, WidgetJobServiceIntent::class.java, JOB_ID, work)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,11 @@
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/list_icon"
|
||||
android:id="@+id/db_icon"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
tools:src="@drawable/day_305" />
|
||||
tools:src="@drawable/cloud_symbol"
|
||||
tools:tint="@color/colour_one" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
@@ -29,7 +30,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/list_day"
|
||||
android:id="@+id/db_condition"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Wednesday" />
|
||||
@@ -53,15 +54,16 @@
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/list_main_temp"
|
||||
android:id="@+id/db_main_temp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
|
||||
android:textSize="28sp"
|
||||
tools:text="28" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/db_temp_unit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:text="°" />
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
android:id="@+id/widget_item_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="3dp"
|
||||
android:layout_marginRight="3dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
@@ -18,33 +20,31 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/widget_item_image"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
tools:src="@drawable/demo_icon" />
|
||||
tools:src="@drawable/cloud_symbol"
|
||||
tools:tint="@color/colour_one" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_item_temp_high"
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:gravity="center"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="20" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_item_temp_low"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:gravity="center"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="12sp"
|
||||
tools:text="11" />
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:id="@+id/widget_item_temp_high"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="20" />
|
||||
<TextView
|
||||
android:id="@+id/db_temp_unit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="°" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
@@ -39,7 +39,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:textSize="60sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/loc_container"
|
||||
@@ -49,7 +48,7 @@
|
||||
android:id="@+id/temp_unit_4"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="9dp"
|
||||
android:text="@string/degrees_c"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 13 KiB |
@@ -8,7 +8,7 @@
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_home"
|
||||
android:name=".ui.home.HomeFragment"
|
||||
android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.home.HomeFragment"
|
||||
android:label="Home"
|
||||
tools:layout="@layout/fragment_home">
|
||||
<action
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<fragment
|
||||
android:id="@+id/furtherDetailsFragment"
|
||||
android:name=".ui.details.FurtherInfoFragment"
|
||||
android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.details.FurtherInfoFragment"
|
||||
android:label="Further Details">
|
||||
<argument
|
||||
android:name="forecast"
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_world"
|
||||
android:name=".ui.world.WorldFragment"
|
||||
android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.world.WorldFragment"
|
||||
android:label="World"
|
||||
tools:layout="@layout/fragment__two">
|
||||
<action
|
||||
@@ -51,12 +51,12 @@
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/addLocationFragment"
|
||||
android:name=".ui.world.AddLocationFragment"
|
||||
android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.world.AddLocationFragment"
|
||||
android:label="Add Weather Location"
|
||||
tools:layout="@layout/activity_add_forecast" />
|
||||
<fragment
|
||||
android:id="@+id/worldItemFragment"
|
||||
android:name=".ui.WorldItemFragment"
|
||||
android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.WorldItemFragment"
|
||||
android:label="Overview"
|
||||
tools:layout="@layout/fragment_home">
|
||||
<action
|
||||
@@ -67,8 +67,9 @@
|
||||
app:popEnterAnim="@anim/fragment_open_enter"
|
||||
app:popExitAnim="@anim/fragment_open_exit" />
|
||||
<argument
|
||||
android:name="weatherDisplay"
|
||||
app:argType="com.appttude.h_mal.atlas_weather.model.forecast.WeatherDisplay" />
|
||||
android:name="locationName"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
</fragment>
|
||||
|
||||
</navigation>
|
||||
@@ -7,7 +7,6 @@
|
||||
<item name="colorPrimaryDark">@color/colour_four</item>
|
||||
<item name="colorAccent">@android:color/white</item>
|
||||
<item name="android:windowBackground">@android:color/black</item>
|
||||
<item name="fontFamily">sans-serif-light</item>
|
||||
<item name="android:textColor">@color/colorAccent</item>
|
||||
<item name="android:statusBarColor">@color/colorPrimaryDark</item>
|
||||
<item name="android:colorControlActivated">@color/colorAccent</item>
|
||||
@@ -17,6 +16,7 @@
|
||||
<item name="materialAlertDialogTheme">@style/YourAlertDialogTheme</item>
|
||||
<item name="bottomNavigationStyle">@style/Widget.MaterialComponents.BottomNavigationView.Colored</item>
|
||||
<item name="floatingActionButtonStyle">@style/Widget.App.FloatingActionButton</item>
|
||||
<!-- <item name="fontFamily">@font/font_family</item>-->
|
||||
</style>
|
||||
|
||||
<style name="YourAlertDialogTheme" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
|
||||
@@ -54,12 +54,12 @@
|
||||
|
||||
|
||||
<style name="TextAppearance.AppCompat.Widget.ActionBar.Title" parent="@android:style/TextAppearance">
|
||||
<item name="android:fontFamily">@font/archeologicaps</item>
|
||||
<!-- <item name="android:fontFamily">@font/archeologicaps</item>-->
|
||||
<!--<item name="android:textColor">@color/colour_five</item>-->
|
||||
</style>
|
||||
|
||||
<style name="titlebar" parent="@android:style/TextAppearance">
|
||||
<item name="android:fontFamily">@font/archeologicaps</item>
|
||||
<!-- <item name="android:fontFamily">@font/archeologicaps</item>-->
|
||||
<!--<item name="android:textColor">@color/colour_five</item>-->
|
||||
</style>
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
</style>
|
||||
|
||||
<style name="icon_style__further_deatils">
|
||||
<item name="android:layout_width">64dp</item>
|
||||
<item name="android:layout_height">64dp</item>
|
||||
<item name="android:layout_width">48dp</item>
|
||||
<item name="android:layout_height">48dp</item>
|
||||
<item name="android:adjustViewBounds">true</item>
|
||||
<item name="android:layout_gravity">center</item>
|
||||
<item name="android:tint">@color/colorAccent</item>
|
||||
|
||||