Drawer and bottom bar.

This commit is contained in:
aminecmi 2019-08-04 16:21:26 +02:00
parent 5e518ddc0e
commit 257d9fa401
12 changed files with 279 additions and 22 deletions

View File

@ -86,6 +86,10 @@ dependencies {
// Dialog for adding a new location // Dialog for adding a new location
implementation 'com.afollestad.material-dialogs:core:3.1.0' implementation 'com.afollestad.material-dialogs:core:3.1.0'
implementation 'com.afollestad.material-dialogs:input:3.1.0' implementation 'com.afollestad.material-dialogs:input:3.1.0'
// drawer
implementation 'co.zsmb:materialdrawer-kt:2.0.1'
implementation "androidx.annotation:annotation:1.1.0"
} }

View File

@ -7,17 +7,29 @@ import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
import android.location.LocationListener import android.location.LocationListener
import android.location.LocationManager import android.location.LocationManager
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.room.Room import androidx.room.Room
import bou.amine.apps.mteo.api.DarkSkyApi import bou.amine.apps.mteo.api.DarkSkyApi
import bou.amine.apps.mteo.api.ForecastResponse import bou.amine.apps.mteo.api.ForecastResponse
import bou.amine.apps.mteo.persistence.MIGRATION_1_2 import bou.amine.apps.mteo.persistence.MIGRATION_1_2
import bou.amine.apps.mteo.persistence.database.AppDatabase import bou.amine.apps.mteo.persistence.database.AppDatabase
import bou.amine.apps.mteo.persistence.entities.LocationView import bou.amine.apps.mteo.persistence.entities.LocationView
import co.zsmb.materialdrawerkt.builders.drawer
import co.zsmb.materialdrawerkt.draweritems.badgeable.primaryItem
import co.zsmb.materialdrawerkt.draweritems.badgeable.secondaryItem
import co.zsmb.materialdrawerkt.draweritems.divider
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.input.input import com.afollestad.materialdialogs.input.input
import com.mikepenz.materialdrawer.Drawer
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
@ -30,11 +42,15 @@ class MainActivity : AppCompatActivity() {
private lateinit var api: DarkSkyApi private lateinit var api: DarkSkyApi
private lateinit var currentLocation: LocationView private lateinit var currentLocation: LocationView
private lateinit var locations: List<LocationView>
private lateinit var drawer: Drawer
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
setSupportActionBar(bottom_app_bar)
api = DarkSkyApi(this@MainActivity) api = DarkSkyApi(this@MainActivity)
@ -43,29 +59,83 @@ class MainActivity : AppCompatActivity() {
AppDatabase::class.java, "mteo-database" AppDatabase::class.java, "mteo-database"
).addMigrations(MIGRATION_1_2).build() ).addMigrations(MIGRATION_1_2).build()
fab.setOnClickListener { checkPermission() }
handleRefresh()
thread { thread {
val locations = db.locationDao().locations() locations = db.locationDao().locations()
runOnUiThread { runOnUiThread {
if (locations.isEmpty()) { if (locations.isEmpty()) {
checkPermission() checkPermission()
} else { } else {
currentLocation = locations[0] selectLocationAndFetch()
fetchForecastData() loadDrawer()
drawer.setSelection(locations[0].id.toLong(), false)
} }
} }
} }
} }
private fun handleRefresh() {
swipeRefreshLayout.setColorSchemeResources(
R.color.colorPrimary,
R.color.colorPrimaryDark,
R.color.colorAccent
)
swipeRefreshLayout.setOnRefreshListener {
fetchForecastData()
}
}
private fun loadDrawer() {
if (::drawer.isInitialized) {
drawer.closeDrawer()
}
drawer = drawer {
toolbar = toolBar
primaryItem("Locations") {
selectable = false
}
locations.map {
secondaryItem(it.name) {
identifier = it.id.toLong()
onClick { _, position, _ ->
selectLocationAndFetch(position - 1)
true
}
}
}
onItemLongClick {_, position, _ ->
val toRemove = locations[position - 1]
locations = locations.filterNot { it == toRemove }
loadDrawer()
thread {
db.locationDao().deleteLocation(toRemove)
}
true
}
}
}
private fun selectLocationAndFetch(position: Int = 0) {
swipeRefreshLayout.isRefreshing = true
currentLocation = locations[position]
fetchForecastData()
}
private fun fetchForecastData() { private fun fetchForecastData() {
thread { thread {
api.forecast(currentLocation.lat.toString(), currentLocation.lng.toString()).enqueue(object : api.forecast(currentLocation.lat.toString(), currentLocation.lng.toString()).enqueue(object :
Callback<ForecastResponse> { Callback<ForecastResponse> {
override fun onFailure(call: Call<ForecastResponse>, t: Throwable) { override fun onFailure(call: Call<ForecastResponse>, t: Throwable) {
Toast.makeText(this@MainActivity, "Can't fetch forecast data !", Toast.LENGTH_LONG).show() Toast.makeText(this@MainActivity, "Can't fetch forecast data !", Toast.LENGTH_LONG).show()
swipeRefreshLayout.isRefreshing = false
} }
override fun onResponse(call: Call<ForecastResponse>, response: Response<ForecastResponse>) { override fun onResponse(call: Call<ForecastResponse>, response: Response<ForecastResponse>) {
Toast.makeText(this@MainActivity, "Ok", Toast.LENGTH_LONG).show() Toast.makeText(this@MainActivity, "Ok", Toast.LENGTH_LONG).show()
swipeRefreshLayout.isRefreshing = false
} }
}) })
@ -114,10 +184,13 @@ class MainActivity : AppCompatActivity() {
mLocationManager.removeUpdates(this) mLocationManager.removeUpdates(this)
MaterialDialog(this@MainActivity).show { MaterialDialog(this@MainActivity).show {
input { _, text -> input { _, text ->
currentLocation = LocationView(location.latitude, location.longitude, text.toString()) locations += LocationView(location.latitude, location.longitude, text.toString())
fetchForecastData() selectLocationAndFetch(locations.size - 1)
thread { thread {
db.locationDao().insertLocation(currentLocation) db.locationDao().insertLocation(currentLocation)
runOnUiThread {
loadDrawer()
}
} }
} }
} }
@ -147,4 +220,22 @@ class MainActivity : AppCompatActivity() {
} }
} }
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.bottom_app_bar, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item!!.itemId) {
R.id.alerts -> Toast.makeText(this@MainActivity, "alerts item is clicked!", Toast.LENGTH_SHORT).show()
R.id.currently -> Toast.makeText(this@MainActivity, "currently item is clicked!", Toast.LENGTH_SHORT).show()
R.id.daily -> Toast.makeText(this@MainActivity, "daily item is clicked!", Toast.LENGTH_SHORT).show()
R.id.hourly -> Toast.makeText(this@MainActivity, "hourly item is clicked!", Toast.LENGTH_SHORT).show()
R.id.minutely -> Toast.makeText(this@MainActivity, "minutely item is clicked!", Toast.LENGTH_SHORT).show()
}
return true
}
} }

View File

@ -1,9 +1,6 @@
package bou.amine.apps.mteo.persistence.dao package bou.amine.apps.mteo.persistence.dao
import androidx.room.Dao import androidx.room.*
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import bou.amine.apps.mteo.persistence.entities.LocationView import bou.amine.apps.mteo.persistence.entities.LocationView
@Dao @Dao
@ -13,4 +10,7 @@ interface LocationsDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertLocation(vararg location: LocationView) fun insertLocation(vararg location: LocationView)
@Delete
fun deleteLocation(tag: LocationView)
} }

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C8.14,2 5,5.14 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.86 -3.14,-7 -7,-7zM16,10h-3v3h-2v-3L8,10L8,8h3L11,5h2v3h3v2z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM16.5,16L8,16c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3l0.14,0.01C8.58,8.28 10.13,7 12,7c2.21,0 4,1.79 4,4h0.5c1.38,0 2.5,1.12 2.5,2.5S17.88,16 16.5,16z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M11,15h2v2h-2zM11,7h2v6h-2zM11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M6,2v6h0.01L6,8.01 10,12l-4,4 0.01,0.01L6,16.01L6,22h12v-5.99h-0.01L18,16l-4,-4 4,-3.99 -0.01,-0.01L18,8L18,2L6,2zM16,16.5L16,20L8,20v-3.5l4,-4 4,4zM12,11.5l-4,-4L8,4h8v3.5l-4,4z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M2,21h19v-3H2v3zM20,8H3c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h17c0.55,0 1,-0.45 1,-1V9c0,-0.55 -0.45,-1 -1,-1zM2,3v3h19V3H2z"/>
</vector>

View File

@ -1,19 +1,83 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity"> tools:context=".MainActivity"
android:fitsSystemWindows="true">
<TextView <androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="wrap_content" android:id="@+id/coordLayout"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:text="Hello World!" android:layout_height="match_parent">
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" <androidx.coordinatorlayout.widget.CoordinatorLayout
app:layout_constraintRight_toRightOf="parent" android:id="@+id/intern_coordLayout"
app:layout_constraintTop_toTopOf="parent"/> android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle"/>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="?android:attr/windowBackground">
</LinearLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</FrameLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="@color/colorPrimary"
app:fabAlignmentMode="end"
style="@style/Widget.MaterialComponents.BottomAppBar"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_add_location"
android:tint="#FFFFFF"
app:layout_anchor="@id/bottom_app_bar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/alerts"
android:icon="@drawable/ic_error_outline"
android:title="Alerts"
android:iconTint="#FFFFFFFF"
app:showAsAction="always"/>
<item
android:id="@+id/currently"
android:icon="@drawable/ic_cloud_circle"
android:title="Currently"
android:iconTint="#FFFFFFFF"
app:showAsAction="always"/>
<item
android:id="@+id/daily"
android:icon="@drawable/ic_view_day"
android:title="Daily"
android:iconTint="#FFFFFFFF"
app:showAsAction="always"/>
<item
android:id="@+id/hourly"
android:icon="@drawable/ic_access_time"
android:title="Hourly"
android:iconTint="#FFFFFFFF"
app:showAsAction="always"/>
<item
android:id="@+id/minutely"
android:icon="@drawable/ic_hourglass_empty"
android:title="Minutely"
android:iconTint="#FFFFFFFF"
app:showAsAction="always"/>
</menu>

View File

@ -1,11 +1,20 @@
<resources> <resources>
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <style name="AppTheme" parent="MaterialDrawerTheme.Light">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item> <item name="colorAccent">@color/colorAccent</item>
</style> </style>
<!-- ToolBar -->
<style name="ToolBarStyle" parent="Theme.AppCompat">
<item name="android:textColorPrimary">#FFFFFFFF</item>
<item name="android:textColorSecondary">#FFFFFFFF</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="actionMenuTextColor">#FFFFFFFF</item>
<!--<item name="actionOverflowButtonStyle">@style/ActionButtonOverflowStyle</item>
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>-->
</style>
</resources> </resources>