This commit is contained in:
purifetchi 2025-06-11 14:43:53 +02:00
parent e63250e25b
commit ebd0e0bea0
14 changed files with 374 additions and 106 deletions

View file

@ -21,6 +21,10 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AddPhoneActivity"
android:exported="false" />
</application>
</manifest>

View file

@ -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("", "", "", "");
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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;

View file

@ -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<List<Phone>> getAllPhones();
}

View file

@ -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");
}
};
}

View file

@ -12,45 +12,68 @@ import java.util.ArrayList;
import java.util.List;
public class PhoneListAdapter extends RecyclerView.Adapter<PhoneListAdapter.PhoneViewHolder> {
private List<Phone> 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<Phone> 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<Phone> phones) {
mPhones = phones;
this.phones = phones;
notifyDataSetChanged();
}
public Phone getPhoneAt(int position) {
return phones.get(position);
}
}

View file

@ -7,20 +7,38 @@ import androidx.lifecycle.LiveData;
import java.util.List;
public class PhoneRepository {
private final PhoneDao mPhoneDao;
private final LiveData<List<Phone>> mAllPhones;
private final PhoneDao dao;
private final LiveData<List<Phone>> phones;
public PhoneRepository(Application application) {
PhoneDatabase db = PhoneDatabase.getDatabase(application);
mPhoneDao = db.phoneDao();
mAllPhones = mPhoneDao.getAllPhones();
dao = db.phoneDao();
phones = dao.getAllPhones();
}
public LiveData<List<Phone>> 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);
});
}
}

View file

@ -9,20 +9,32 @@ import androidx.lifecycle.LiveData;
import java.util.List;
public class PhoneViewModel extends AndroidViewModel {
private final PhoneRepository mRepository;
private final LiveData<List<Phone>> mAllPhones;
private final PhoneRepository repo;
private final LiveData<List<Phone>> phones;
public PhoneViewModel(@NonNull Application application) {
super(application);
mRepository = new PhoneRepository(application);
mAllPhones = mRepository.getAllPhones();
repo = new PhoneRepository(application);
phones = repo.getAllPhones();
}
public LiveData<List<Phone>> 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);
}
}

View file

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

View file

@ -1,70 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
android:padding="16dp"
android:fitsSystemWindows="true">
<TextView
android:id="@+id/labelManufacturer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/producent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/editManufacturer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textPersonName"
app:layout_constraintStart_toEndOf="@id/labelManufacturer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBaseline_toBaselineOf="@id/labelManufacturer"
android:layout_marginStart="8dp" />
<TextView
android:id="@+id/labelModel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/model"
app:layout_constraintTop_toBottomOf="@id/labelManufacturer"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="16dp" />
<EditText
android:id="@+id/editModel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textPersonName"
app:layout_constraintStart_toEndOf="@id/labelModel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBaseline_toBaselineOf="@id/labelModel"
android:layout_marginStart="8dp" />
<TextView
android:id="@+id/labelAndroidVersion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/wersja_android"
app:layout_constraintTop_toBottomOf="@id/labelModel"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="16dp" />
<EditText
android:id="@+id/editAndroidVersion"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="number"
app:layout_constraintStart_toEndOf="@id/labelAndroidVersion"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBaseline_toBaselineOf="@id/labelAndroidVersion"
android:layout_marginStart="8dp" />
<TextView
android:id="@+id/labelWebsite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/strona"
app:layout_constraintTop_toBottomOf="@id/labelAndroidVersion"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="16dp" />
<EditText
android:id="@+id/editWebsite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textUri"
app:layout_constraintStart_toEndOf="@id/labelWebsite"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBaseline_toBaselineOf="@id/labelWebsite"
android:layout_marginStart="8dp" />
<LinearLayout
android:layout_width="match_parent"
android:id="@+id/buttonLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical">
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">
<EditText
android:id="@+id/editManufacturer"
android:layout_width="match_parent"
<Button
android:id="@+id/buttonWebsite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Manufacturer"
android:inputType="textPersonName" />
android:layout_weight="1"
android:text="@string/strona_" />
<EditText
android:id="@+id/editModel"
android:layout_width="match_parent"
<Button
android:id="@+id/buttonCancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Model"
android:inputType="textPersonName" />
android:layout_weight="1"
android:text="@string/anuluj" />
<EditText
android:id="@+id/editAndroidVersion"
android:layout_width="match_parent"
<Button
android:id="@+id/buttonSave"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Android version"
android:inputType="number" />
<EditText
android:id="@+id/editWebsite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Web site"
android:inputType="textUri" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginTop="16dp"
android:weightSum="3">
<Button
android:id="@+id/buttonWebsite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="WEB SITE" />
<Button
android:id="@+id/buttonCancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="CANCEL" />
<Button
android:id="@+id/buttonSave"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="SAVE" />
</LinearLayout>
android:layout_weight="1"
android:text="@string/zapisz" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -13,5 +13,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabMain"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:src="@drawable/baseline_add_24"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,7 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textView"
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp"
android:textSize="18sp" />
android:padding="12dp">
<TableRow>
<TextView
android:id="@+id/textProducer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Producer"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textModel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Model"
android:textSize="18sp" />
</TableRow>
</TableLayout>

View file

@ -1,4 +1,12 @@
<resources>
<string name="app_name">lab2</string>
<string name="wyczy_dane">Wyczyść dane</string>
<string name="producent">Producent</string>
<string name="model">Model</string>
<string name="wersja_android">Wersja Android</string>
<string name="strona">Strona</string>
<string name="strona_">STRONA</string>
<string name="anuluj">ANULUJ</string>
<string name="zapisz">ZAPISZ</string>
<string name="to_pole_nie_mo_e_by_puste">To pole nie może być puste</string>
</resources>