diff --git a/lab2/app/src/main/AndroidManifest.xml b/lab2/app/src/main/AndroidManifest.xml index 2ae6be9..419f42e 100644 --- a/lab2/app/src/main/AndroidManifest.xml +++ b/lab2/app/src/main/AndroidManifest.xml @@ -21,6 +21,10 @@ + + \ No newline at end of file diff --git a/lab2/app/src/main/java/com/example/lab2/AddPhoneActivity.java b/lab2/app/src/main/java/com/example/lab2/AddPhoneActivity.java index 8726d1a..64f78be 100644 --- a/lab2/app/src/main/java/com/example/lab2/AddPhoneActivity.java +++ b/lab2/app/src/main/java/com/example/lab2/AddPhoneActivity.java @@ -3,12 +3,13 @@ package com.example.lab2; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.view.View; import android.widget.Button; import android.widget.EditText; import androidx.appcompat.app.AppCompatActivity; +import java.io.Serializable; + public class AddPhoneActivity extends AppCompatActivity { private EditText manufacturerInput; @@ -19,6 +20,9 @@ public class AddPhoneActivity extends AppCompatActivity { private Button cancelButton; private Button websiteButton; + private Phone phone; + private boolean isEditing = false; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -32,8 +36,32 @@ public class AddPhoneActivity extends AppCompatActivity { cancelButton = findViewById(R.id.buttonCancel); websiteButton = findViewById(R.id.buttonWebsite); + manufacturerInput.setOnFocusChangeListener((v, hasFocus) -> { + if (!hasFocus && manufacturerInput.getText().toString().trim().isEmpty()) { + manufacturerInput.setError(getString(R.string.to_pole_nie_mo_e_by_puste)); + } + }); + + modelInput.setOnFocusChangeListener((v, hasFocus) -> { + if (!hasFocus && modelInput.getText().toString().trim().isEmpty()) { + modelInput.setError(getString(R.string.to_pole_nie_mo_e_by_puste)); + } + }); + + androidVersionInput.setOnFocusChangeListener((v, hasFocus) -> { + if (!hasFocus && androidVersionInput.getText().toString().trim().isEmpty()) { + androidVersionInput.setError(getString(R.string.to_pole_nie_mo_e_by_puste)); + } + }); + + websiteInput.setOnFocusChangeListener((v, hasFocus) -> { + if (!hasFocus && websiteInput.getText().toString().trim().isEmpty()) { + websiteInput.setError(getString(R.string.to_pole_nie_mo_e_by_puste)); + } + }); + websiteButton.setOnClickListener(view -> { - String url = websiteInput.getText().toString(); + String url = websiteInput.getText().toString().trim(); if (!url.startsWith("http")) { url = "http://" + url; } @@ -44,13 +72,53 @@ public class AddPhoneActivity extends AppCompatActivity { cancelButton.setOnClickListener(view -> finish()); saveButton.setOnClickListener(view -> { + boolean isValid = true; + + if (manufacturerInput.getText().toString().trim().isEmpty()) { + manufacturerInput.setError(getString(R.string.to_pole_nie_mo_e_by_puste)); + isValid = false; + } + + if (modelInput.getText().toString().trim().isEmpty()) { + modelInput.setError(getString(R.string.to_pole_nie_mo_e_by_puste)); + isValid = false; + } + + if (androidVersionInput.getText().toString().trim().isEmpty()) { + androidVersionInput.setError(getString(R.string.to_pole_nie_mo_e_by_puste)); + isValid = false; + } + + if (websiteInput.getText().toString().trim().isEmpty()) { + websiteInput.setError(getString(R.string.to_pole_nie_mo_e_by_puste)); + isValid = false; + } + + if (!isValid) return; + Intent resultIntent = new Intent(); - resultIntent.putExtra("manufacturer", manufacturerInput.getText().toString()); - resultIntent.putExtra("model", modelInput.getText().toString()); - resultIntent.putExtra("androidVersion", androidVersionInput.getText().toString()); - resultIntent.putExtra("website", websiteInput.getText().toString()); + phone.producer = manufacturerInput.getText().toString().trim(); + phone.model = modelInput.getText().toString().trim(); + phone.version = androidVersionInput.getText().toString().trim(); + phone.website = websiteInput.getText().toString().trim(); + + resultIntent.putExtra("phone", phone); + resultIntent.putExtra("editing", isEditing); setResult(RESULT_OK, resultIntent); finish(); }); + + Intent intent = getIntent(); + if (intent.hasExtra("edited_phone")) { + Serializable serialized = intent.getSerializableExtra("edited_phone"); + phone = (Phone) serialized; + modelInput.setText(phone.model); + manufacturerInput.setText(phone.producer); + websiteInput.setText(phone.website); + androidVersionInput.setText(phone.version); + isEditing = true; + } else { + phone = new Phone("", "", "", ""); + } } } diff --git a/lab2/app/src/main/java/com/example/lab2/MainActivity.java b/lab2/app/src/main/java/com/example/lab2/MainActivity.java index eadca82..4d3ca6c 100644 --- a/lab2/app/src/main/java/com/example/lab2/MainActivity.java +++ b/lab2/app/src/main/java/com/example/lab2/MainActivity.java @@ -1,21 +1,24 @@ package com.example.lab2; +import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; -import androidx.activity.EdgeToEdge; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; -import androidx.core.graphics.Insets; -import androidx.core.view.ViewCompat; -import androidx.core.view.WindowInsetsCompat; import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.floatingactionbutton.FloatingActionButton; + public class MainActivity extends AppCompatActivity { - private PhoneViewModel mPhoneViewModel; + private PhoneViewModel phoneViewModel; + private FloatingActionButton fab; + + private final int ACTIVITY_REQUEST_CODE = 1; @Override protected void onCreate(Bundle savedInstanceState) { @@ -27,8 +30,34 @@ public class MainActivity extends AppCompatActivity { recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(this)); - mPhoneViewModel = new ViewModelProvider(this).get(PhoneViewModel.class); - mPhoneViewModel.getAllPhones().observe(this, adapter::setPhones); + phoneViewModel = new ViewModelProvider(this).get(PhoneViewModel.class); + phoneViewModel.getAllPhones().observe(this, adapter::setPhones); + + fab = findViewById(R.id.fabMain); + fab.setOnClickListener(view -> { + startActivityForResult(new Intent(this, AddPhoneActivity.class), ACTIVITY_REQUEST_CODE); + }); + + adapter.setOnItemClickListener(phone -> { + Intent intent = new Intent(MainActivity.this, AddPhoneActivity.class); + intent.putExtra("edited_phone", phone); + startActivityForResult(intent, ACTIVITY_REQUEST_CODE); + }); + + new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, + ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder, + @NonNull RecyclerView.ViewHolder target) { + return false; + } + + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + phoneViewModel.delete(adapter.getPhoneAt(viewHolder.getAdapterPosition())); + } + }).attachToRecyclerView(recyclerView); } @Override @@ -40,9 +69,24 @@ public class MainActivity extends AppCompatActivity { @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (item.getItemId() == R.id.clear_data) { - mPhoneViewModel.deleteAll(); + phoneViewModel.deleteAll(); return true; } return super.onOptionsItemSelected(item); } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) { + Phone editedPhone = (Phone)data.getSerializableExtra("phone"); + + if (data.getBooleanExtra("editing", false)) { + phoneViewModel.update(editedPhone); + } else { + phoneViewModel.insert(editedPhone); + } + } + } + } diff --git a/lab2/app/src/main/java/com/example/lab2/Phone.java b/lab2/app/src/main/java/com/example/lab2/Phone.java index 8f22d7e..fb30e76 100644 --- a/lab2/app/src/main/java/com/example/lab2/Phone.java +++ b/lab2/app/src/main/java/com/example/lab2/Phone.java @@ -4,8 +4,10 @@ import androidx.annotation.NonNull; import androidx.room.Entity; import androidx.room.PrimaryKey; +import java.io.Serializable; + @Entity(tableName = "phones") -public class Phone { +public class Phone implements Serializable { @PrimaryKey(autoGenerate = true) public int id; diff --git a/lab2/app/src/main/java/com/example/lab2/PhoneDao.java b/lab2/app/src/main/java/com/example/lab2/PhoneDao.java index e3091bf..3fca22c 100644 --- a/lab2/app/src/main/java/com/example/lab2/PhoneDao.java +++ b/lab2/app/src/main/java/com/example/lab2/PhoneDao.java @@ -2,7 +2,9 @@ package com.example.lab2; import androidx.lifecycle.LiveData; import androidx.room.Dao; +import androidx.room.Delete; import androidx.room.Insert; +import androidx.room.Update; import androidx.room.OnConflictStrategy; import androidx.room.Query; @@ -16,6 +18,12 @@ public interface PhoneDao { @Query("DELETE FROM phones") void deleteAll(); + @Delete + void delete(Phone phone); + + @Update + void update(Phone phone); + @Query("SELECT * FROM phones ORDER BY producer ASC") LiveData> getAllPhones(); } diff --git a/lab2/app/src/main/java/com/example/lab2/PhoneDatabase.java b/lab2/app/src/main/java/com/example/lab2/PhoneDatabase.java index a42e7d7..68ae0f2 100644 --- a/lab2/app/src/main/java/com/example/lab2/PhoneDatabase.java +++ b/lab2/app/src/main/java/com/example/lab2/PhoneDatabase.java @@ -25,8 +25,8 @@ public abstract class PhoneDatabase extends RoomDatabase { if (INSTANCE == null) { synchronized (PhoneDatabase.class) { if (INSTANCE == null) { - context.deleteDatabase("phone_database"); - Log.i("tag", "deleted db"); + //context.deleteDatabase("phone_database"); + //Log.i("tag", "deleted db"); INSTANCE = Room.databaseBuilder(context.getApplicationContext(), PhoneDatabase.class, "phone_database") .addCallback(sRoomDatabaseCallback) @@ -49,7 +49,7 @@ public abstract class PhoneDatabase extends RoomDatabase { dao.insert(new Phone("Google", "Pixel 4", "11", "https://google.com")); dao.insert(new Phone("Samsung", "Galaxy S21", "12", "https://samsung.com")); }); - Log.i("", "remake"); + //Log.i("", "remake"); } }; } diff --git a/lab2/app/src/main/java/com/example/lab2/PhoneListAdapter.java b/lab2/app/src/main/java/com/example/lab2/PhoneListAdapter.java index 4da4ab8..449d4be 100644 --- a/lab2/app/src/main/java/com/example/lab2/PhoneListAdapter.java +++ b/lab2/app/src/main/java/com/example/lab2/PhoneListAdapter.java @@ -12,45 +12,68 @@ import java.util.ArrayList; import java.util.List; public class PhoneListAdapter extends RecyclerView.Adapter { - private List mPhones = new ArrayList<>(); - private final LayoutInflater mInflater; - - public PhoneListAdapter(Context context) { - mInflater = LayoutInflater.from(context); + public interface OnItemClickListener { + void onItemClick(Phone phone); } - static class PhoneViewHolder extends RecyclerView.ViewHolder { - private final TextView phoneItemView; + private List phones = new ArrayList<>(); + private OnItemClickListener listener; + private final LayoutInflater inflater; + + public PhoneListAdapter(Context context) { + inflater = LayoutInflater.from(context); + } + + class PhoneViewHolder extends RecyclerView.ViewHolder { + private final TextView producerView; + private final TextView modelView; public PhoneViewHolder(View itemView) { super(itemView); - phoneItemView = itemView.findViewById(R.id.textView); + producerView = itemView.findViewById(R.id.textProducer); + modelView = itemView.findViewById(R.id.textModel); + + itemView.setOnClickListener(v -> { + int position = getAdapterPosition(); + if (listener != null && position != RecyclerView.NO_POSITION) { + listener.onItemClick(phones.get(position)); + } + }); } - public void bind(String text) { - phoneItemView.setText(text); + public void bind(Phone phone) { + producerView.setText(phone.producer); + modelView.setText(phone.model); } } + public void setOnItemClickListener(OnItemClickListener listener) { + this.listener = listener; + } + @Override public PhoneViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View itemView = mInflater.inflate(R.layout.phone_list_item, parent, false); + View itemView = inflater.inflate(R.layout.phone_list_item, parent, false); return new PhoneViewHolder(itemView); } @Override public void onBindViewHolder(PhoneViewHolder holder, int position) { - Phone current = mPhones.get(position); - holder.bind(current.producer + " " + current.model); + Phone current = phones.get(position); + holder.bind(current); } @Override public int getItemCount() { - return mPhones.size(); + return phones.size(); } public void setPhones(List phones) { - mPhones = phones; + this.phones = phones; notifyDataSetChanged(); } + + public Phone getPhoneAt(int position) { + return phones.get(position); + } } diff --git a/lab2/app/src/main/java/com/example/lab2/PhoneRepository.java b/lab2/app/src/main/java/com/example/lab2/PhoneRepository.java index cb58401..4534b72 100644 --- a/lab2/app/src/main/java/com/example/lab2/PhoneRepository.java +++ b/lab2/app/src/main/java/com/example/lab2/PhoneRepository.java @@ -7,20 +7,38 @@ import androidx.lifecycle.LiveData; import java.util.List; public class PhoneRepository { - private final PhoneDao mPhoneDao; - private final LiveData> mAllPhones; + private final PhoneDao dao; + private final LiveData> phones; public PhoneRepository(Application application) { PhoneDatabase db = PhoneDatabase.getDatabase(application); - mPhoneDao = db.phoneDao(); - mAllPhones = mPhoneDao.getAllPhones(); + dao = db.phoneDao(); + phones = dao.getAllPhones(); } public LiveData> getAllPhones() { - return mAllPhones; + return phones; } public void deleteAll() { - PhoneDatabase.databaseWriteExecutor.execute(mPhoneDao::deleteAll); + PhoneDatabase.databaseWriteExecutor.execute(dao::deleteAll); + } + + public void delete(Phone phone) { + PhoneDatabase.databaseWriteExecutor.execute(() -> { + dao.delete(phone); + }); + } + + public void update(Phone phone) { + PhoneDatabase.databaseWriteExecutor.execute(() -> { + dao.update(phone); + }); + } + + public void insert(Phone phone) { + PhoneDatabase.databaseWriteExecutor.execute(() -> { + dao.insert(phone); + }); } } diff --git a/lab2/app/src/main/java/com/example/lab2/PhoneViewModel.java b/lab2/app/src/main/java/com/example/lab2/PhoneViewModel.java index 982b9f2..621eabf 100644 --- a/lab2/app/src/main/java/com/example/lab2/PhoneViewModel.java +++ b/lab2/app/src/main/java/com/example/lab2/PhoneViewModel.java @@ -9,20 +9,32 @@ import androidx.lifecycle.LiveData; import java.util.List; public class PhoneViewModel extends AndroidViewModel { - private final PhoneRepository mRepository; - private final LiveData> mAllPhones; + private final PhoneRepository repo; + private final LiveData> phones; public PhoneViewModel(@NonNull Application application) { super(application); - mRepository = new PhoneRepository(application); - mAllPhones = mRepository.getAllPhones(); + repo = new PhoneRepository(application); + phones = repo.getAllPhones(); } public LiveData> getAllPhones() { - return mAllPhones; + return phones; } public void deleteAll() { - mRepository.deleteAll(); + repo.deleteAll(); + } + + public void delete(Phone phone) { + repo.delete(phone); + } + + public void insert(Phone phone) { + repo.insert(phone); + } + + public void update(Phone phone) { + repo.update(phone); } } diff --git a/lab2/app/src/main/res/drawable/baseline_add_24.xml b/lab2/app/src/main/res/drawable/baseline_add_24.xml new file mode 100644 index 0000000..9f83b8f --- /dev/null +++ b/lab2/app/src/main/res/drawable/baseline_add_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/lab2/app/src/main/res/layout/activity_add_phone.xml b/lab2/app/src/main/res/layout/activity_add_phone.xml index 1be30f5..034a9b6 100644 --- a/lab2/app/src/main/res/layout/activity_add_phone.xml +++ b/lab2/app/src/main/res/layout/activity_add_phone.xml @@ -1,70 +1,118 @@ - + android:padding="16dp" + android:fitsSystemWindows="true"> + + + + + + + + + + + + + + + + + android:orientation="horizontal" + android:gravity="center" + android:weightSum="3" + android:layout_marginTop="24dp" + app:layout_constraintTop_toBottomOf="@id/labelWebsite" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"> - + android:layout_weight="1" + android:text="@string/strona_" /> - + android:layout_weight="1" + android:text="@string/anuluj" /> - - - - - - -