diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..c098947 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Criminal Intent 2020 \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..681f41a --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,116 @@ + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..7ae9cb6 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..5cd135a --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..f88d4b8 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + 1.8 + + + + + + + + \ No newline at end of file diff --git a/.idea/render.experimental.xml b/.idea/render.experimental.xml new file mode 100644 index 0000000..8ec256a --- /dev/null +++ b/.idea/render.experimental.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/Crime.java b/Crime.java new file mode 100644 index 0000000..af553e0 --- /dev/null +++ b/Crime.java @@ -0,0 +1,44 @@ +package ru.orlovph.criminalintent2020; + +import java.util.Date; +import java.util.UUID; + +public class Crime { + private UUID id; + private String title; + private Date date; + private boolean solved; + + public Crime(){ + id = UUID.randomUUID(); + date = new Date(); + } + + public UUID getId() { + return id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public boolean isSolved() { + return solved; + } + + public void setSolved(boolean solved) { + this.solved = solved; + } +} diff --git a/CrimeFragment.java b/CrimeFragment.java new file mode 100644 index 0000000..8501326 --- /dev/null +++ b/CrimeFragment.java @@ -0,0 +1,121 @@ +package ru.orlovph.criminalintent2020; + + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import java.util.Date; +import java.util.UUID; + +import static android.widget.CompoundButton.*; + +public class CrimeFragment extends Fragment { + + private static final String ARG_CRIME_ID = "crime_id"; + private static final String DIALOG_DATE = "DialogDate"; + + private static final int REQUEST_DATE = 0; + + private Crime mCrime; + private EditText titleField; + private Button btnDate; + private CheckBox solvedCheckBox; + + +// method that accepts a UUID, creates an arguments bundle, +// creates a fragment instance, and then attaches the arguments to the fragment + public static CrimeFragment newInstance(UUID crimeID){ + Bundle args = new Bundle(); + args.putSerializable(ARG_CRIME_ID, crimeID); + + CrimeFragment fragment = new CrimeFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + UUID crimeID = (UUID) getArguments().getSerializable(ARG_CRIME_ID); + mCrime = CrimeLab.get(getActivity()).getCrime(crimeID); + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_crime, container, false); + + titleField = view.findViewById(R.id.crime_title); + titleField.setText(mCrime.getTitle()); + titleField.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mCrime.setTitle(s.toString()); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + btnDate = view.findViewById(R.id.crime_date); + updateDate(); + btnDate.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View v) { + FragmentManager fragmentManager = getFragmentManager(); + DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate()); + dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE); + dialog.show(fragmentManager,DIALOG_DATE); + } + }); + + solvedCheckBox = view.findViewById(R.id.crime_solved); + solvedCheckBox.setChecked(mCrime.isSolved()); + solvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mCrime.setSolved(isChecked); + } + }); + + return view; + } + + private void updateDate() { + btnDate.setText(mCrime.getDate().toString()); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (resultCode != Activity.RESULT_OK){ + return; + } + + if (requestCode == REQUEST_DATE){ + Date date = (Date) data + .getSerializableExtra(DatePickerFragment.EXTRA_DATE); + mCrime.setDate(date); + updateDate(); + } + } +} diff --git a/CrimeLab.java b/CrimeLab.java new file mode 100644 index 0000000..9493bfe --- /dev/null +++ b/CrimeLab.java @@ -0,0 +1,44 @@ +package ru.orlovph.criminalintent2020; + +import android.content.Context; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +// Singleton class - a class that allows only one +// instance of itself to be created +public class CrimeLab { + private static CrimeLab sCrimeLab; + + private List mCrimes; + + public static CrimeLab get(Context context) { + if (sCrimeLab == null) { + sCrimeLab = new CrimeLab(context); + } + return sCrimeLab; + } + + private CrimeLab(Context context) { + mCrimes = new ArrayList<>(); + } + + public void addCrime(Crime crime){ + mCrimes.add(crime); + } + + public List getCrimes(){ + return mCrimes; + } + + public Crime getCrime(UUID id){ + for(Crime crime: mCrimes){ + if (crime.getId().equals(id)){ + return crime; + } + } + return null; + } + +} diff --git a/CrimeListActivity.java b/CrimeListActivity.java new file mode 100644 index 0000000..a7d02b8 --- /dev/null +++ b/CrimeListActivity.java @@ -0,0 +1,10 @@ +package ru.orlovph.criminalintent2020; + +import androidx.fragment.app.Fragment; + +public class CrimeListActivity extends SingleFragmentActivity { + @Override + protected Fragment createFragment() { + return new CrimeListFragment(); + } +} diff --git a/CrimeListFragment.java b/CrimeListFragment.java new file mode 100644 index 0000000..599e4ff --- /dev/null +++ b/CrimeListFragment.java @@ -0,0 +1,187 @@ +package ru.orlovph.criminalintent2020; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.List; + +public class CrimeListFragment extends Fragment { + private static final String SAVED_SUBTITLE_VISIBLE = "subtitle"; + private RecyclerView crimeRecyclerView; + private CrimeAdapter crimeAdapter; + private boolean mSubtitleVisible; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container + , @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_crime_list, container, false); + + crimeRecyclerView = view.findViewById(R.id.crime_recycler_view); + crimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + + if (savedInstanceState !=null){ + mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE); + } + + updateUI(); + return view; + } + + @Override + public void onResume() { + super.onResume(); + updateUI(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(SAVED_SUBTITLE_VISIBLE, mSubtitleVisible); + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.fragment_crime_list, menu); + + MenuItem subtitleItem = menu.findItem(R.id.show_subtitle); + if (mSubtitleVisible){ + subtitleItem.setTitle(R.string.hide_subtitle); + }else{ + subtitleItem.setTitle(R.string.show_subtitle); + } + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case R.id.new_crime: + Crime crime = new Crime(); + CrimeLab.get(getActivity()).addCrime(crime); + Intent intent = CrimePagerActivity + .newIntent(getActivity(), crime.getId()); + startActivity(intent); + return true; + case R.id.show_subtitle: + mSubtitleVisible = !mSubtitleVisible; + getActivity().invalidateOptionsMenu(); + updateSubtitle(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private void updateSubtitle() { + CrimeLab crimeLab = CrimeLab.get(getActivity()); + int crimeCount = crimeLab.getCrimes().size(); + String subtitle = getString(R.string.subtitle_format, crimeCount); + + if (!mSubtitleVisible){ + subtitle=null; + } + + AppCompatActivity activity = (AppCompatActivity) getActivity(); + activity.getSupportActionBar().setSubtitle(subtitle); + } + + private void updateUI() { + CrimeLab crimeLab = CrimeLab.get(getActivity()); + List crimes = crimeLab.getCrimes(); + + if (crimeAdapter == null) { + crimeAdapter = new CrimeAdapter(crimes); + crimeRecyclerView.setAdapter(crimeAdapter); + } else { + crimeAdapter.notifyDataSetChanged(); + } + + updateSubtitle(); + } + + // CRIME HOLDER + private class CrimeHolder extends RecyclerView.ViewHolder + implements View.OnClickListener { + + private TextView titleTextView; + private TextView dateTextView; + private ImageView solvedImage; + + private Crime mCrime; + + public CrimeHolder(LayoutInflater inflater, ViewGroup parent) { + super(inflater.inflate(R.layout.list_item_crime, parent, false)); + itemView.setOnClickListener(this); + + titleTextView = itemView.findViewById(R.id.crime_title); + dateTextView = itemView.findViewById(R.id.crime_date); + solvedImage = itemView.findViewById(R.id.crime_solved); + } + + public void bind(Crime bCrime) { + + mCrime = bCrime; + titleTextView.setText(mCrime.getTitle()); + dateTextView.setText(mCrime.getDate().toString()); + solvedImage.setVisibility(bCrime.isSolved() ? View.VISIBLE : View.GONE); + } + + @Override + public void onClick(View v) { + Intent intent = CrimePagerActivity.newIntent(getActivity(), mCrime.getId()); + startActivity(intent); + } + } + + // CRIME ADAPTER + private class CrimeAdapter extends RecyclerView.Adapter { + private List mCrimes; + + public CrimeAdapter(List crimes) { + mCrimes = crimes; + } + + @NonNull + @Override + public CrimeHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + LayoutInflater layoutInflater = LayoutInflater.from(getActivity()); + return new CrimeHolder(layoutInflater, parent); + } + + @Override + public void onBindViewHolder(@NonNull CrimeHolder holder, int position) { + Crime crime = mCrimes.get(position); + holder.bind(crime); + } + + @Override + public int getItemCount() { + return mCrimes.size(); + } + } +} diff --git a/CrimePagerActivity.java b/CrimePagerActivity.java new file mode 100644 index 0000000..9ebb5db --- /dev/null +++ b/CrimePagerActivity.java @@ -0,0 +1,69 @@ +package ru.orlovph.criminalintent2020; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager2.adapter.FragmentStateAdapter; +import androidx.viewpager2.widget.ViewPager2; + +import java.util.List; +import java.util.UUID; + +public class CrimePagerActivity extends AppCompatActivity { + + private static final String EXTRA_CRIME_ID = + "ru.orlovph.criminalintent2020.crime_id"; + + private ViewPager2 mViewPager; + private List mCrimes; + + public static Intent newIntent(Context packageContext, UUID crimeID){ + Intent intent = new Intent(packageContext, CrimePagerActivity.class); + intent.putExtra(EXTRA_CRIME_ID, crimeID); + return intent; + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_crime_pager); + + UUID crimeID = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID); + + mViewPager = findViewById(R.id.crime_view_pager); + +// get data set from CrimeLab – the List of crimes + mCrimes = CrimeLab.get(this).getCrimes(); +// get the activity’s instance of FragmentManager + FragmentManager fragmentManager = getSupportFragmentManager(); +// set the adapter to be an unnamed instance of FragmentStateAdapter + mViewPager.setAdapter(new FragmentStateAdapter(fragmentManager,getLifecycle()) { + @NonNull + @Override + public Fragment createFragment(int position) { + Crime crime = mCrimes.get(position); + return CrimeFragment.newInstance(crime.getId()); + } + + @Override + public int getItemCount() { + return mCrimes.size(); + } + }); + + for (int i = 0; i < mCrimes.size(); i++) { + if (mCrimes.get(i).getId().equals(crimeID)){ + mViewPager.setCurrentItem(i); + break; + } + } + } +} diff --git a/DatePickerFragment.java b/DatePickerFragment.java new file mode 100644 index 0000000..f1151ba --- /dev/null +++ b/DatePickerFragment.java @@ -0,0 +1,81 @@ +package ru.orlovph.criminalintent2020; + +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.DatePicker; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +public class DatePickerFragment extends DialogFragment { + private static final String ARG_DATE = "date"; + public static final String EXTRA_DATE = "ru.orlovph.criminalintent2020.date"; + + private DatePicker mDatePicker; + + public static DatePickerFragment newInstance(Date date){ + Bundle args = new Bundle(); + args.putSerializable(ARG_DATE,date); + + DatePickerFragment fragment = new DatePickerFragment(); + fragment.setArguments(args); + return fragment; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + Date date = (Date) getArguments().getSerializable(ARG_DATE); + + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int year = calendar.get(Calendar.YEAR); + int month = calendar.get(Calendar.MONTH); + int day = calendar.get(Calendar.DAY_OF_MONTH); + + View view = LayoutInflater.from(getActivity()) + .inflate(R.layout.dialog_date,null); + + mDatePicker = view.findViewById(R.id.dialog_date_picker); + mDatePicker.init(year,month,day,null); + + return new AlertDialog.Builder(getActivity()) + .setView(view) + .setTitle(R.string.date_picker_title) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + int year = mDatePicker.getYear(); + int month = mDatePicker.getMonth(); + int day = mDatePicker.getDayOfMonth(); + Date date = new GregorianCalendar(year,month,day).getTime(); + sendResult(Activity.RESULT_OK,date); + } + }) + .create(); + } + + private void sendResult(int resultCode, Date date){ + if (getTargetFragment() == null){ + return; + } + + Intent intent = new Intent(); + intent.putExtra(EXTRA_DATE, date); + + getTargetFragment() + .onActivityResult(getTargetRequestCode(),resultCode,intent); + } +} diff --git a/SingleFragmentActivity.java b/SingleFragmentActivity.java new file mode 100644 index 0000000..3ea757a --- /dev/null +++ b/SingleFragmentActivity.java @@ -0,0 +1,29 @@ +package ru.orlovph.criminalintent2020; + +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +public abstract class SingleFragmentActivity extends AppCompatActivity { + + // abstract method used to instantiate the fragment + protected abstract Fragment createFragment(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_fragment); + + FragmentManager fragmentManager = getSupportFragmentManager(); + Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container); + + if (fragment == null){ + fragment = createFragment(); + fragmentManager.beginTransaction() + .add(R.id.fragment_container, fragment) + .commit(); + } + } +} diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..7452f6d --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,36 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + + defaultConfig { + applicationId "ru.orlovph.criminalintent2020" + minSdkVersion 21 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation "androidx.recyclerview:recyclerview:1.1.0" + implementation "androidx.viewpager2:viewpager2:1.0.0" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/ru/orlovph/criminalintent2020/ExampleInstrumentedTest.java b/app/src/androidTest/java/ru/orlovph/criminalintent2020/ExampleInstrumentedTest.java new file mode 100644 index 0000000..8de96b0 --- /dev/null +++ b/app/src/androidTest/java/ru/orlovph/criminalintent2020/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package ru.orlovph.criminalintent2020; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("ru.orlovph.criminalintent2020", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d0c3a37 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/Crime.java b/app/src/main/java/ru/orlovph/criminalintent2020/Crime.java new file mode 100644 index 0000000..04924e5 --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/Crime.java @@ -0,0 +1,48 @@ +package ru.orlovph.criminalintent2020; + +import java.util.Date; +import java.util.UUID; + +public class Crime { + private UUID mID; + private String title; + private Date date; + private boolean solved; + + public Crime() { + this(UUID.randomUUID()); + } + + public Crime(UUID id){ + mID = id; + date = new Date(); + } + + public UUID getmID() { + return mID; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public boolean isSolved() { + return solved; + } + + public void setSolved(boolean solved) { + this.solved = solved; + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/CrimeActivity.java b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeActivity.java new file mode 100644 index 0000000..5aa51da --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeActivity.java @@ -0,0 +1,26 @@ +package ru.orlovph.criminalintent2020; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import android.os.Bundle; + +public class CrimeActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_crime); + + FragmentManager fragmentManager = getSupportFragmentManager(); + Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container); + + if (fragment == null){ + fragment = new CrimeFragment(); + fragmentManager.beginTransaction() + .add(R.id.fragment_container, fragment) + .commit(); + } + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/CrimeFragment.java b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeFragment.java new file mode 100644 index 0000000..0113d9c --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeFragment.java @@ -0,0 +1,128 @@ +package ru.orlovph.criminalintent2020; + + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import java.util.Date; +import java.util.UUID; + +import static android.widget.CompoundButton.*; + +public class CrimeFragment extends Fragment { + + private static final String ARG_CRIME_ID = "crime_id"; + private static final String DIALOG_DATE = "DialogDate"; + + private static final int REQUEST_DATE = 0; + + private Crime mCrime; + private EditText titleField; + private Button btnDate; + private CheckBox solvedCheckBox; + + +// method that accepts a UUID, creates an arguments bundle, +// creates a fragment instance, and then attaches the arguments to the fragment + public static CrimeFragment newInstance(UUID crimeID){ + Bundle args = new Bundle(); + args.putSerializable(ARG_CRIME_ID, crimeID); + + CrimeFragment fragment = new CrimeFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + UUID crimeID = (UUID) getArguments().getSerializable(ARG_CRIME_ID); + mCrime = CrimeLab.get(getActivity()).getCrime(crimeID); + } + + @Override + public void onPause() { + super.onPause(); + + CrimeLab.get(getActivity()) + .updateCrime(mCrime); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_crime, container, false); + + titleField = view.findViewById(R.id.crime_title); + titleField.setText(mCrime.getTitle()); + titleField.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mCrime.setTitle(s.toString()); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + btnDate = view.findViewById(R.id.crime_date); + updateDate(); + btnDate.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View v) { + FragmentManager fragmentManager = getFragmentManager(); + DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate()); + dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE); + dialog.show(fragmentManager,DIALOG_DATE); + } + }); + + solvedCheckBox = view.findViewById(R.id.crime_solved); + solvedCheckBox.setChecked(mCrime.isSolved()); + solvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mCrime.setSolved(isChecked); + } + }); + + return view; + } + + private void updateDate() { + btnDate.setText(mCrime.getDate().toString()); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (resultCode != Activity.RESULT_OK){ + return; + } + + if (requestCode == REQUEST_DATE){ + Date date = (Date) data + .getSerializableExtra(DatePickerFragment.EXTRA_DATE); + mCrime.setDate(date); + updateDate(); + } + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/CrimeLab.java b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeLab.java new file mode 100644 index 0000000..84798b5 --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeLab.java @@ -0,0 +1,111 @@ +package ru.orlovph.criminalintent2020; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import ru.orlovph.criminalintent2020.database.CrimeBaseHelper; +import ru.orlovph.criminalintent2020.database.CrimeCursorWrapper; +import ru.orlovph.criminalintent2020.database.CrimeDbSchema.CrimeTable; + +// Singleton class - a class that allows only one +// instance of itself to be created +public class CrimeLab { + private static CrimeLab sCrimeLab; + + private Context mContext; + private SQLiteDatabase mDatabase; + + public static CrimeLab get(Context context) { + if (sCrimeLab == null) { + sCrimeLab = new CrimeLab(context); + } + return sCrimeLab; + } + + private CrimeLab(Context context) { + mContext = context.getApplicationContext(); + mDatabase = new CrimeBaseHelper(mContext) + .getWritableDatabase(); + + } + + public void addCrime(Crime crime) { + ContentValues values = getContentValues(crime); + + mDatabase.insert(CrimeTable.NAME, null, values); + } + + public List getCrimes() { + ArrayList crimes = new ArrayList<>(); + + CrimeCursorWrapper cursor = queryCrimes(null,null); + + try { + cursor.moveToFirst(); + while(!cursor.isAfterLast()){ + crimes.add(cursor.getCrime()); + cursor.moveToNext(); + } + }finally { + cursor.close(); + } + return crimes; + } + + public Crime getCrime(UUID id) { + CrimeCursorWrapper cursor = queryCrimes( + CrimeTable.Cols.UUID + " = ?", + new String[]{id.toString()} + ); + try{ + if (cursor.getCount() == 0){ + return null; + } + + cursor.moveToFirst(); + return cursor.getCrime(); + }finally{ + cursor.close(); + } + } + + public void updateCrime(Crime crime) { + String uuidString = crime.getmID().toString(); + ContentValues values = getContentValues(crime); + + mDatabase.update(CrimeTable.NAME, values, + CrimeTable.Cols.UUID + " = ?", + new String[]{uuidString}); + } + + private CrimeCursorWrapper queryCrimes(String whereClause, String[] whereArgs){ + Cursor cursor = mDatabase.query( + CrimeTable.NAME, + null, // columns - null selects all columns + whereClause, + whereArgs, + null, // groupBy + null, // having + null // orderBy + ); + + return new CrimeCursorWrapper(cursor); + } + + private static ContentValues getContentValues(Crime crime) { + ContentValues values = new ContentValues(); + values.put(CrimeTable.Cols.UUID, crime.getmID().toString()); + values.put(CrimeTable.Cols.TITLE, crime.getTitle()); + values.put(CrimeTable.Cols.DATE, crime.getDate().getTime()); + values.put(CrimeTable.Cols.SOLVED, crime.isSolved() ? 1 : 0); + + return values; + } + +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/CrimeListActivity.java b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeListActivity.java new file mode 100644 index 0000000..a7d02b8 --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeListActivity.java @@ -0,0 +1,10 @@ +package ru.orlovph.criminalintent2020; + +import androidx.fragment.app.Fragment; + +public class CrimeListActivity extends SingleFragmentActivity { + @Override + protected Fragment createFragment() { + return new CrimeListFragment(); + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/CrimeListFragment.java b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeListFragment.java new file mode 100644 index 0000000..58fde69 --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/CrimeListFragment.java @@ -0,0 +1,189 @@ +package ru.orlovph.criminalintent2020; + +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.List; + +public class CrimeListFragment extends Fragment { + private static final String SAVED_SUBTITLE_VISIBLE = "subtitle"; + private RecyclerView crimeRecyclerView; + private CrimeAdapter crimeAdapter; + private boolean mSubtitleVisible; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container + , @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_crime_list, container, false); + + crimeRecyclerView = view.findViewById(R.id.crime_recycler_view); + crimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + + if (savedInstanceState !=null){ + mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE); + } + + updateUI(); + return view; + } + + @Override + public void onResume() { + super.onResume(); + updateUI(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(SAVED_SUBTITLE_VISIBLE, mSubtitleVisible); + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.fragment_crime_list, menu); + + MenuItem subtitleItem = menu.findItem(R.id.show_subtitle); + if (mSubtitleVisible){ + subtitleItem.setTitle(R.string.hide_subtitle); + }else{ + subtitleItem.setTitle(R.string.show_subtitle); + } + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case R.id.new_crime: + Crime crime = new Crime(); + CrimeLab.get(getActivity()).addCrime(crime); + Intent intent = CrimePagerActivity + .newIntent(getActivity(), crime.getmID()); + startActivity(intent); + return true; + case R.id.show_subtitle: + mSubtitleVisible = !mSubtitleVisible; + getActivity().invalidateOptionsMenu(); + updateSubtitle(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private void updateSubtitle() { + CrimeLab crimeLab = CrimeLab.get(getActivity()); + int crimeCount = crimeLab.getCrimes().size(); + String subtitle = getString(R.string.subtitle_format, crimeCount); + + if (!mSubtitleVisible){ + subtitle=null; + } + + AppCompatActivity activity = (AppCompatActivity) getActivity(); + activity.getSupportActionBar().setSubtitle(subtitle); + } + + private void updateUI() { + CrimeLab crimeLab = CrimeLab.get(getActivity()); + List crimes = crimeLab.getCrimes(); + + if (crimeAdapter == null) { + crimeAdapter = new CrimeAdapter(crimes); + crimeRecyclerView.setAdapter(crimeAdapter); + } else { + crimeAdapter.setCrimes(crimes); + crimeAdapter.notifyDataSetChanged(); + } + + updateSubtitle(); + } + + // CRIME HOLDER + private class CrimeHolder extends RecyclerView.ViewHolder + implements View.OnClickListener { + + private TextView titleTextView; + private TextView dateTextView; + private ImageView solvedImage; + + private Crime mCrime; + + public CrimeHolder(LayoutInflater inflater, ViewGroup parent) { + super(inflater.inflate(R.layout.list_item_crime, parent, false)); + itemView.setOnClickListener(this); + + titleTextView = itemView.findViewById(R.id.crime_title); + dateTextView = itemView.findViewById(R.id.crime_date); + solvedImage = itemView.findViewById(R.id.crime_solved); + } + + public void bind(Crime bCrime) { + + mCrime = bCrime; + titleTextView.setText(mCrime.getTitle()); + dateTextView.setText(mCrime.getDate().toString()); + solvedImage.setVisibility(bCrime.isSolved() ? View.VISIBLE : View.GONE); + } + + @Override + public void onClick(View v) { + Intent intent = CrimePagerActivity.newIntent(getActivity(), mCrime.getmID()); + startActivity(intent); + } + } + + // CRIME ADAPTER + private class CrimeAdapter extends RecyclerView.Adapter { + private List mCrimes; + + public CrimeAdapter(List crimes) { + mCrimes = crimes; + } + + @NonNull + @Override + public CrimeHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + LayoutInflater layoutInflater = LayoutInflater.from(getActivity()); + return new CrimeHolder(layoutInflater, parent); + } + + @Override + public void onBindViewHolder(@NonNull CrimeHolder holder, int position) { + Crime crime = mCrimes.get(position); + holder.bind(crime); + } + + @Override + public int getItemCount() { + return mCrimes.size(); + } + + public void setCrimes(List crimes){ + mCrimes = crimes; + } + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/CrimePagerActivity.java b/app/src/main/java/ru/orlovph/criminalintent2020/CrimePagerActivity.java new file mode 100644 index 0000000..3bb6410 --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/CrimePagerActivity.java @@ -0,0 +1,67 @@ +package ru.orlovph.criminalintent2020; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.viewpager2.adapter.FragmentStateAdapter; +import androidx.viewpager2.widget.ViewPager2; + +import java.util.List; +import java.util.UUID; + +public class CrimePagerActivity extends AppCompatActivity { + + private static final String EXTRA_CRIME_ID = + "ru.orlovph.criminalintent2020.crime_id"; + + private ViewPager2 mViewPager; + private List mCrimes; + + public static Intent newIntent(Context packageContext, UUID crimeID){ + Intent intent = new Intent(packageContext, CrimePagerActivity.class); + intent.putExtra(EXTRA_CRIME_ID, crimeID); + return intent; + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_crime_pager); + + UUID crimeID = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID); + + mViewPager = findViewById(R.id.crime_view_pager); + +// get data set from CrimeLab – the List of crimes + mCrimes = CrimeLab.get(this).getCrimes(); +// get the activity’s instance of FragmentManager + FragmentManager fragmentManager = getSupportFragmentManager(); +// set the adapter to be an unnamed instance of FragmentStateAdapter + mViewPager.setAdapter(new FragmentStateAdapter(fragmentManager,getLifecycle()) { + @NonNull + @Override + public Fragment createFragment(int position) { + Crime crime = mCrimes.get(position); + return CrimeFragment.newInstance(crime.getmID()); + } + + @Override + public int getItemCount() { + return mCrimes.size(); + } + }); + + for (int i = 0; i < mCrimes.size(); i++) { + if (mCrimes.get(i).getmID().equals(crimeID)){ + mViewPager.setCurrentItem(i); + break; + } + } + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/DatePickerFragment.java b/app/src/main/java/ru/orlovph/criminalintent2020/DatePickerFragment.java new file mode 100644 index 0000000..f1151ba --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/DatePickerFragment.java @@ -0,0 +1,81 @@ +package ru.orlovph.criminalintent2020; + +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.DatePicker; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +public class DatePickerFragment extends DialogFragment { + private static final String ARG_DATE = "date"; + public static final String EXTRA_DATE = "ru.orlovph.criminalintent2020.date"; + + private DatePicker mDatePicker; + + public static DatePickerFragment newInstance(Date date){ + Bundle args = new Bundle(); + args.putSerializable(ARG_DATE,date); + + DatePickerFragment fragment = new DatePickerFragment(); + fragment.setArguments(args); + return fragment; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + Date date = (Date) getArguments().getSerializable(ARG_DATE); + + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int year = calendar.get(Calendar.YEAR); + int month = calendar.get(Calendar.MONTH); + int day = calendar.get(Calendar.DAY_OF_MONTH); + + View view = LayoutInflater.from(getActivity()) + .inflate(R.layout.dialog_date,null); + + mDatePicker = view.findViewById(R.id.dialog_date_picker); + mDatePicker.init(year,month,day,null); + + return new AlertDialog.Builder(getActivity()) + .setView(view) + .setTitle(R.string.date_picker_title) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + int year = mDatePicker.getYear(); + int month = mDatePicker.getMonth(); + int day = mDatePicker.getDayOfMonth(); + Date date = new GregorianCalendar(year,month,day).getTime(); + sendResult(Activity.RESULT_OK,date); + } + }) + .create(); + } + + private void sendResult(int resultCode, Date date){ + if (getTargetFragment() == null){ + return; + } + + Intent intent = new Intent(); + intent.putExtra(EXTRA_DATE, date); + + getTargetFragment() + .onActivityResult(getTargetRequestCode(),resultCode,intent); + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/SingleFragmentActivity.java b/app/src/main/java/ru/orlovph/criminalintent2020/SingleFragmentActivity.java new file mode 100644 index 0000000..3ea757a --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/SingleFragmentActivity.java @@ -0,0 +1,29 @@ +package ru.orlovph.criminalintent2020; + +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +public abstract class SingleFragmentActivity extends AppCompatActivity { + + // abstract method used to instantiate the fragment + protected abstract Fragment createFragment(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_fragment); + + FragmentManager fragmentManager = getSupportFragmentManager(); + Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container); + + if (fragment == null){ + fragment = createFragment(); + fragmentManager.beginTransaction() + .add(R.id.fragment_container, fragment) + .commit(); + } + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeBaseHelper.java b/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeBaseHelper.java new file mode 100644 index 0000000..0da6df8 --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeBaseHelper.java @@ -0,0 +1,30 @@ +package ru.orlovph.criminalintent2020.database; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import ru.orlovph.criminalintent2020.database.CrimeDbSchema.CrimeTable; + +public class CrimeBaseHelper extends SQLiteOpenHelper { + private static final int VERSION = 1; + private static final String DATABASE_NAME = "crimeBase.db"; + + public CrimeBaseHelper(Context context){ + super(context, DATABASE_NAME, null, VERSION); + } + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("create table "+ CrimeTable.NAME + "(" + + " _id integer primary key autoincrement, " + + CrimeTable.Cols.UUID + ", " + + CrimeTable.Cols.TITLE + ", " + + CrimeTable.Cols.DATE + ", " + + CrimeTable.Cols.SOLVED + ")"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeCursorWrapper.java b/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeCursorWrapper.java new file mode 100644 index 0000000..064f0ca --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeCursorWrapper.java @@ -0,0 +1,30 @@ +package ru.orlovph.criminalintent2020.database; + +import android.database.Cursor; +import android.database.CursorWrapper; + +import java.util.Date; +import java.util.UUID; + +import ru.orlovph.criminalintent2020.Crime; +import ru.orlovph.criminalintent2020.database.CrimeDbSchema.CrimeTable; + +public class CrimeCursorWrapper extends CursorWrapper { + public CrimeCursorWrapper(Cursor cursor) { + super(cursor); + } + + public Crime getCrime(){ + String uuidString = getString(getColumnIndex(CrimeTable.Cols.UUID)); + String title = getString(getColumnIndex(CrimeTable.Cols.TITLE)); + long date = getLong(getColumnIndex(CrimeTable.Cols.DATE)); + int isSolved = getInt(getColumnIndex(CrimeTable.Cols.SOLVED)); + + Crime crime = new Crime(UUID.fromString(uuidString)); + crime.setTitle(title); + crime.setDate(new Date(date)); + crime.setSolved(isSolved != 0); + + return crime; + } +} diff --git a/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeDbSchema.java b/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeDbSchema.java new file mode 100644 index 0000000..b88b61d --- /dev/null +++ b/app/src/main/java/ru/orlovph/criminalintent2020/database/CrimeDbSchema.java @@ -0,0 +1,14 @@ +package ru.orlovph.criminalintent2020.database; + +public class CrimeDbSchema { + public static final class CrimeTable{ + public static final String NAME = "crimes"; + + public static final class Cols{ + public static final String UUID = "uuid"; + public static final String TITLE = "title"; + public static final String DATE = "date"; + public static final String SOLVED = "solved"; + } + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_solved.png b/app/src/main/res/drawable-hdpi/ic_solved.png new file mode 100644 index 0000000..e9b9263 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_solved.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_solved.png b/app/src/main/res/drawable-mdpi/ic_solved.png new file mode 100644 index 0000000..9548d3c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_solved.png differ diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/ic_solved.png b/app/src/main/res/drawable-xhdpi/ic_solved.png new file mode 100644 index 0000000..6ab438d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_solved.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_solved.png b/app/src/main/res/drawable-xxhdpi/ic_solved.png new file mode 100644 index 0000000..ca05191 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_solved.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_solved.png b/app/src/main/res/drawable-xxxhdpi/ic_solved.png new file mode 100644 index 0000000..15d3cf4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_solved.png differ diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml new file mode 100644 index 0000000..e3979cd --- /dev/null +++ b/app/src/main/res/drawable/ic_add.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_crime.xml b/app/src/main/res/layout/activity_crime.xml new file mode 100644 index 0000000..7a7bcbb --- /dev/null +++ b/app/src/main/res/layout/activity_crime.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_fragment.xml b/app/src/main/res/layout/activity_fragment.xml new file mode 100644 index 0000000..7a7bcbb --- /dev/null +++ b/app/src/main/res/layout/activity_fragment.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_date.xml b/app/src/main/res/layout/dialog_date.xml new file mode 100644 index 0000000..350dcac --- /dev/null +++ b/app/src/main/res/layout/dialog_date.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_crime.xml b/app/src/main/res/layout/fragment_crime.xml new file mode 100644 index 0000000..1c8b980 --- /dev/null +++ b/app/src/main/res/layout/fragment_crime.xml @@ -0,0 +1,38 @@ + + + + + + + + + +