diff --git a/README.md b/README.md new file mode 100644 index 0000000..332b55c --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Archaeological_Fieldwork +Repository for submission for the Android programming course at the OTH Regensburg in the winter semester 2020/2021. + +### Purpose of the application +In the final version, places are to be stored, displayed and managed together with title, description and pictures. +In an extended version, the data storage takes place in Firebase and notes and ratings can be given for the places. diff --git a/app/build.gradle b/app/build.gradle index a667c87..12b18c8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,7 +9,7 @@ android { defaultConfig { applicationId "com.archaeologicalfieldwork" minSdkVersion 23 - targetSdkVersion 30 + targetSdkVersion 29 versionCode 1 versionName "1.0" @@ -34,4 +34,11 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + //*************Own Implementations************* + //Anko Logger + implementation 'org.jetbrains.anko:anko-commons:0.10.8' + + //Material Design + implementation 'com.google.android.material:material:1.2.0' + } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 19975a6..1acc635 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,19 +3,24 @@ package="com.archaeologicalfieldwork"> - + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/archaeologicalfieldwork/MainActivity.kt b/app/src/main/java/com/archaeologicalfieldwork/MainActivity.kt deleted file mode 100644 index fc45c30..0000000 --- a/app/src/main/java/com/archaeologicalfieldwork/MainActivity.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.archaeologicalfieldwork - -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle - -class MainActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/archaeologicalfieldwork/activities/SpotActivity.kt b/app/src/main/java/com/archaeologicalfieldwork/activities/SpotActivity.kt new file mode 100644 index 0000000..7d3ead4 --- /dev/null +++ b/app/src/main/java/com/archaeologicalfieldwork/activities/SpotActivity.kt @@ -0,0 +1,75 @@ +package com.archaeologicalfieldwork.activities + +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import kotlinx.android.synthetic.main.activity_spot.* +import org.jetbrains.anko.info +import org.jetbrains.anko.toast +import org.jetbrains.anko.AnkoLogger +import com.archaeologicalfieldwork.R +import com.archaeologicalfieldwork.main.MainApp +import com.archaeologicalfieldwork.models.SpotModel + +class SpotActivity : AppCompatActivity(), AnkoLogger { + + var spot = SpotModel() + lateinit var app: MainApp + var edit = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_spot) + toolbarAdd.title = title + setSupportActionBar(toolbarAdd) + info("Add Spot Activity started...") + + app = application as MainApp + + // Retrieve passed Spot info via Parcelize + if (intent.hasExtra("spot_edit")) { + edit = true + + spot = intent.extras?.getParcelable("spot_edit")!! + spotTitle.setText(spot.title) + spotDescription.setText(spot.desription) + + btnAddSpot.setText(R.string.button_save_spot) + } + + // Handle Add Button Press + btnAddSpot.setOnClickListener() { + spot.title = spotTitle.text.toString() + spot.desription = spotDescription.text.toString() + + if (spot.title.isEmpty()) { + toast(R.string.enter_spot_title) + } else { + if (edit) { + app.spots.update(spot.copy()) + } else { + app.spots.create(spot.copy()) + } + info("add Button pressed: ${spot}") + app.spots.logAll() + setResult(AppCompatActivity.RESULT_OK) + finish() + } + } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate(R.menu.menu_new_spot, menu) + return super.onCreateOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.item_cancel -> { + finish() + } + } + return super.onOptionsItemSelected(item) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/archaeologicalfieldwork/activities/SpotAdapter.kt b/app/src/main/java/com/archaeologicalfieldwork/activities/SpotAdapter.kt new file mode 100644 index 0000000..531a878 --- /dev/null +++ b/app/src/main/java/com/archaeologicalfieldwork/activities/SpotAdapter.kt @@ -0,0 +1,45 @@ +package com.archaeologicalfieldwork.activities + +import android.view.View +import android.view.ViewGroup +import android.view.LayoutInflater +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.card_spot.view.* +import com.archaeologicalfieldwork.R +import com.archaeologicalfieldwork.models.SpotModel + +interface SpotListener { + fun onSpotClick(spot: SpotModel) +} + +class SpotAdapter constructor( + private var spots: List, + private val listener: SpotListener +) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainHolder { + return MainHolder( + LayoutInflater.from(parent?.context).inflate( + R.layout.card_spot, + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: MainHolder, position: Int) { + val spot = spots[holder.adapterPosition] + holder.bind(spot, listener) + } + + override fun getItemCount(): Int = spots.size + + class MainHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) { + + fun bind(spot: SpotModel, listener: SpotListener) { + itemView.spotTitle_Card.text = spot.title + itemView.spotDescription_Card.text = spot.desription + itemView.setOnClickListener { listener.onSpotClick(spot) } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/archaeologicalfieldwork/activities/SpotListActivity.kt b/app/src/main/java/com/archaeologicalfieldwork/activities/SpotListActivity.kt new file mode 100644 index 0000000..85d9d5e --- /dev/null +++ b/app/src/main/java/com/archaeologicalfieldwork/activities/SpotListActivity.kt @@ -0,0 +1,54 @@ +package com.archaeologicalfieldwork.activities + +import android.content.Intent +import android.os.Bundle +import android.view.* +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager +import kotlinx.android.synthetic.main.activity_spot_list.* +import org.jetbrains.anko.AnkoLogger +import org.jetbrains.anko.intentFor +import org.jetbrains.anko.startActivityForResult +import com.archaeologicalfieldwork.R +import com.archaeologicalfieldwork.main.MainApp +import com.archaeologicalfieldwork.models.SpotModel + + +class SpotListActivity : AppCompatActivity(), SpotListener, AnkoLogger { + + lateinit var app: MainApp + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_spot_list) + app = application as MainApp + + toolbar.title = title + setSupportActionBar(toolbar) + + val layoutManager = LinearLayoutManager(this) + recyclerView.layoutManager = layoutManager + recyclerView.adapter = SpotAdapter(app.spots.findAll(), this) + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate(R.menu.menu_main, menu) + return super.onCreateOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.item_add -> startActivityForResult(0) + } + return super.onOptionsItemSelected(item) + } + + override fun onSpotClick(spot: SpotModel) { + startActivityForResult(intentFor().putExtra("spot_edit", spot), 0) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + recyclerView.adapter?.notifyDataSetChanged() + super.onActivityResult(requestCode, resultCode, data) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/archaeologicalfieldwork/main/MainApp.kt b/app/src/main/java/com/archaeologicalfieldwork/main/MainApp.kt new file mode 100644 index 0000000..5cc66f7 --- /dev/null +++ b/app/src/main/java/com/archaeologicalfieldwork/main/MainApp.kt @@ -0,0 +1,16 @@ +package com.archaeologicalfieldwork.main + +import android.app.Application +import org.jetbrains.anko.info +import org.jetbrains.anko.AnkoLogger +import com.archaeologicalfieldwork.models.SpotMemStore + +class MainApp : Application(), AnkoLogger { + + val spots = SpotMemStore() + + override fun onCreate() { + super.onCreate() + info("Archaelogical Fieldwork started") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/archaeologicalfieldwork/models/SpotMemStore.kt b/app/src/main/java/com/archaeologicalfieldwork/models/SpotMemStore.kt new file mode 100644 index 0000000..b9402fd --- /dev/null +++ b/app/src/main/java/com/archaeologicalfieldwork/models/SpotMemStore.kt @@ -0,0 +1,38 @@ +package com.archaeologicalfieldwork.models + +import java.util.ArrayList +import org.jetbrains.anko.info +import org.jetbrains.anko.AnkoLogger + +var lastId = 0L + +internal fun getId(): Long { + return lastId++ +} + +class SpotMemStore : SpotStore, AnkoLogger { + + val spots = ArrayList() + + override fun findAll(): List { + return spots + } + + override fun create(spot: SpotModel) { + spot.id = getId() + spots.add(spot) + logAll() + } + + override fun update(spot: SpotModel) { + var foundSpot: SpotModel? = spots.find { spot_iterator -> spot_iterator.id == spot.id } + if (foundSpot != null) { + foundSpot.title = spot.title + foundSpot.desription = spot.desription + } + } + + fun logAll() { + spots.forEach { info("${it}") } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/archaeologicalfieldwork/models/SpotModel.kt b/app/src/main/java/com/archaeologicalfieldwork/models/SpotModel.kt new file mode 100644 index 0000000..58acb35 --- /dev/null +++ b/app/src/main/java/com/archaeologicalfieldwork/models/SpotModel.kt @@ -0,0 +1,11 @@ +package com.archaeologicalfieldwork.models + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class SpotModel( + var id: Long = 0, + var title: String = "", + var desription: String = "" +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/archaeologicalfieldwork/models/SpotStore.kt b/app/src/main/java/com/archaeologicalfieldwork/models/SpotStore.kt new file mode 100644 index 0000000..355d38f --- /dev/null +++ b/app/src/main/java/com/archaeologicalfieldwork/models/SpotStore.kt @@ -0,0 +1,7 @@ +package com.archaeologicalfieldwork.models + +interface SpotStore { + fun findAll(): List + fun create(spot: SpotModel) + fun update(spot: SpotModel) +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index f22a759..0000000 --- a/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_spot.xml b/app/src/main/res/layout/activity_spot.xml new file mode 100644 index 0000000..22f1f36 --- /dev/null +++ b/app/src/main/res/layout/activity_spot.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + +