diff --git a/Assignments/CriminalIntent13/.gitignore b/Assignments/CriminalIntent13/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/Assignments/CriminalIntent13/.gitignore @@ -0,0 +1,15 @@ +*.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 +local.properties diff --git a/Assignments/CriminalIntent13/CriminalIntent.zip b/Assignments/CriminalIntent13/CriminalIntent.zip new file mode 100644 index 0000000..11b9e69 Binary files /dev/null and b/Assignments/CriminalIntent13/CriminalIntent.zip differ diff --git a/Assignments/CriminalIntent13/app/.gitignore b/Assignments/CriminalIntent13/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/Assignments/CriminalIntent13/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/Assignments/CriminalIntent13/app/build.gradle.kts b/Assignments/CriminalIntent13/app/build.gradle.kts new file mode 100644 index 0000000..f9c6fb5 --- /dev/null +++ b/Assignments/CriminalIntent13/app/build.gradle.kts @@ -0,0 +1,40 @@ +plugins { + alias(libs.plugins.androidApplication) +} + +android { + namespace = "asdv.lisset.criminalintent" + compileSdk = 34 + + defaultConfig { + applicationId = "asdv.lisset.criminalintent13_toolbar" + minSdk = 21 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation(libs.appcompat) + implementation(libs.material) + implementation(libs.activity) + implementation(libs.constraintlayout) + testImplementation(libs.junit) + androidTestImplementation(libs.ext.junit) + androidTestImplementation(libs.espresso.core) +} \ No newline at end of file diff --git a/Assignments/CriminalIntent13/app/proguard-rules.pro b/Assignments/CriminalIntent13/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/Assignments/CriminalIntent13/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 \ No newline at end of file diff --git a/Assignments/CriminalIntent13/app/src/androidTest/java/asdv/lisset/criminalintent/ExampleInstrumentedTest.java b/Assignments/CriminalIntent13/app/src/androidTest/java/asdv/lisset/criminalintent/ExampleInstrumentedTest.java new file mode 100644 index 0000000..bf28542 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/androidTest/java/asdv/lisset/criminalintent/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package asdv.lisset.criminalintent; + +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("asdv.lisset.criminalintent", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/Assignments/CriminalIntent13/app/src/main/AndroidManifest.xml b/Assignments/CriminalIntent13/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..154348e --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/Crime.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/Crime.java new file mode 100644 index 0000000..ee23ff3 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/Crime.java @@ -0,0 +1,49 @@ +package asdv.lisset.criminalintent; + +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() { + this(UUID.randomUUID()); + //this.id = UUID.randomUUID(); + //this.date = new Date(); + } + + public Crime(UUID uuid) { + id = uuid; + 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/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeActivity.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeActivity.java new file mode 100644 index 0000000..82543ea --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeActivity.java @@ -0,0 +1,35 @@ +package asdv.lisset.criminalintent; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +import java.io.Serializable; +import java.util.UUID; + +public class CrimeActivity extends SingleFragmentActivity { + + @Override + protected Fragment createFragment() { +// return new CrimeFragment(); + UUID crimeId = (UUID) getIntent() + .getSerializableExtra(EXTRA_CRIME_ID); + return CrimeFragment.newInstance(crimeId); + } + + //To know which crime we create a fragment for + public static final String EXTRA_CRIME_ID = + "com.bignerdranch.android.criminalintent.crime_id"; + public static Intent newIntent(Context + packageContext, UUID crimeId) { + Intent intent = new Intent(packageContext, + CrimeActivity.class); + intent.putExtra(EXTRA_CRIME_ID,(Serializable) crimeId); + return intent; + } +} \ No newline at end of file diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeFragment.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeFragment.java new file mode 100644 index 0000000..fc04060 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeFragment.java @@ -0,0 +1,189 @@ +package asdv.lisset.criminalintent; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +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 java.sql.Time; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.UUID; + +public class CrimeFragment extends Fragment { + private Crime crime; + private EditText titleField; + private Button dateButton; + private CheckBox solvedCheckBox; + private Button timeButton; + private static final String ARG_CRIME_ID = + "crime_id"; + private static final String DIALOG_DATE = + "DialogDate"; + private static final String DIALOG_TIME = + "DialogTime"; + private static final int REQUEST_DATE = 0; + + private static final int REQUEST_TIME = 888; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + UUID crimeId = (UUID)getArguments().getSerializable(ARG_CRIME_ID); + crime = CrimeLab.get(getActivity()).getCrime(crimeId); + } + + @Override + public void onPause() { + super.onPause(); + CrimeLab.get(getActivity()) + .updateCrime(crime); + } + + @Override + public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_crime, container, false); + + //date button + SimpleDateFormat dt = new SimpleDateFormat("EEEE, MMMM d, yyyy"); + String s = dt.format(this.crime.getDate()); + this.dateButton = v.findViewById(R.id.button_crime_date); + this.dateButton.setText(s); + + //Date Listener + dateButton.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View v) + { + FragmentManager manager = getFragmentManager(); + DatePickerFragment dialog = DatePickerFragment.newInstance(crime.getDate()); + //Sets target fragment here + dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE); + dialog.show(manager, DIALOG_DATE); + } + }); + + this.timeButton = v.findViewById(R.id.button_crime_time); + this.timeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentManager manager = getFragmentManager(); + TimePickerFragment dialog = TimePickerFragment.newInstance(crime.getDate()); + //Sets target fragment here + dialog.setTargetFragment(CrimeFragment.this, REQUEST_TIME); + dialog.show(manager, DIALOG_TIME); + } + }); + + //checkbox + this.solvedCheckBox = v.findViewById(R.id.checkBox_crime_solved); + this.solvedCheckBox.setChecked(crime.isSolved()); + //Checkbox Listener + this.solvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + CrimeFragment.this.crime.setSolved(isChecked); + } + }); + + //title + this.titleField= v.findViewById(R.id.edit_text_crime_title); + this.titleField.setText(crime.getTitle()); + //Title Listener + titleField.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + //left blank + } + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + crime.setTitle(s.toString()); + } + @Override + public void afterTextChanged(Editable s) { + //left blank + } + + }); + return v; + } + + //Create Instance of Crime Fragment using Crime Id + 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; + + } + + //Retrieve date change from DatePickerFragment + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + + if (requestCode == REQUEST_DATE) { + Date date = (Date) data + .getSerializableExtra(DatePickerFragment.EXTRA_DATE); + crime.setDate(date); + updateDate(); + updateTime(); + } + if (requestCode == REQUEST_TIME) + { + Date time = (Date) data.getSerializableExtra(TimePickerFragment.EXTRA_TIME); + + // Create a new Date with the updated time + Date updatedDateTime = new Date(crime.getDate().getTime()); // Create a copy of the original date + updatedDateTime.setHours(time.getHours()); + updatedDateTime.setMinutes(time.getMinutes()); + + //change crime data + crime.setDate(updatedDateTime); + updateTime(); + } + } + private void updateDate() + { + Log.d("TIME: " , crime.getDate().toString()); + SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMMM d, yyyy", Locale.getDefault()); + String formattedDate = dateFormat.format(crime.getDate()); + dateButton.setText(crime.getDate().toString()); + } + private void updateTime() { + + int hour = crime.getDate().getHours(); + int minute = crime.getDate().getMinutes(); + + String amPm = (hour >= 12) ? "PM" : "AM"; + if (hour > 12) { + hour -= 12; // Convert to 12-hour + } else if (hour == 0) { + hour = 12; // Midnight 12 AM in 12-hour + } + + String formattedTime = String.format( + Locale.getDefault(), + "%02d:%02d %s", + hour, minute, amPm); + // Update the timeButton text + timeButton.setText(formattedTime); + } +} \ No newline at end of file diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeLab.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeLab.java new file mode 100644 index 0000000..ea4ae3c --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeLab.java @@ -0,0 +1,100 @@ +package asdv.lisset.criminalintent; + +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 asdv.lisset.criminalintent.database.CrimeBaseHelper; +import asdv.lisset.criminalintent.database.CrimeCursorWrapper; +import asdv.lisset.criminalintent.database.CrimeDbSchema; + +public class CrimeLab { + private static CrimeLab crimeLab; + private List crimes; + private Context mContext; + private SQLiteDatabase mDatabase; + public static CrimeLab get(Context context) { + if (crimeLab == null) { + crimeLab = new CrimeLab(context); + } + return crimeLab; + } + private CrimeLab(Context context) { + mContext = context.getApplicationContext(); + mDatabase = new CrimeBaseHelper(mContext).getWritableDatabase(); + //crimes = new ArrayList<>(); + } + public void addCrime(Crime c) { + //crimes.add(c); + ContentValues values = getContentValues(c); + mDatabase.insert(CrimeDbSchema.CrimeTable.NAME, null, values); + } + public List getCrimes() { + //return crimes; + List 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( + CrimeDbSchema.CrimeTable.Cols.UUID + " = ?", + new String[] { id.toString() } + ); + try { + if (cursor.getCount() == 0) { + return null; + } + } finally { + cursor.close(); + } + cursor.moveToFirst(); + return cursor.getCrime(); + } + + public void updateCrime(Crime crime) { + String uuidString = crime.getId().toString(); + ContentValues values = getContentValues(crime); + + mDatabase.update(CrimeDbSchema.CrimeTable.NAME, values, + CrimeDbSchema.CrimeTable.Cols.UUID + " = ?", + new String[] {uuidString}); + } + private CrimeCursorWrapper queryCrimes(String whereClause, String[] whereArgs) { + Cursor cursor = mDatabase.query( + CrimeDbSchema.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(CrimeDbSchema.CrimeTable.Cols.UUID, + crime.getId().toString()); + values.put(CrimeDbSchema.CrimeTable.Cols.TITLE, + crime.getTitle()); + values.put(CrimeDbSchema.CrimeTable.Cols.DATE, + crime.getDate().getTime()); + values.put(CrimeDbSchema.CrimeTable.Cols.SOLVED, + crime.isSolved() ? 1 : 0); + return values; + } +} diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeListActivity.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeListActivity.java new file mode 100644 index 0000000..53932f2 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeListActivity.java @@ -0,0 +1,10 @@ +package asdv.lisset.criminalintent; + +import androidx.fragment.app.Fragment; + +public class CrimeListActivity extends SingleFragmentActivity{ + @Override + protected Fragment createFragment() { + return new CrimeListFragment(); + } +} diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeListFragment.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeListFragment.java new file mode 100644 index 0000000..0c6036f --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimeListFragment.java @@ -0,0 +1,207 @@ +package asdv.lisset.criminalintent; + +import android.content.Intent; +import android.os.Bundle; +import android.text.Layout; +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.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 RecyclerView crimeRecyclerView; + private CrimeAdapter adapter; + private boolean subtitleVisible; + + private static final String SAVED_SUBTITLE_VISIBLE = "subtitle"; + + private void updateSubtitle() { + CrimeLab crimeLab = CrimeLab.get(getActivity()); + int crimeCount = crimeLab.getCrimes().size(); + String subtitle = getString(R.string.subtitle_format, crimeCount); + if (!subtitleVisible) { + subtitle = null; + } + AppCompatActivity activity = (AppCompatActivity)getActivity(); + activity.getSupportActionBar().setSubtitle(subtitle); + } + + private void updateUI(){ + CrimeLab crimeLab = CrimeLab.get(getActivity()); + List crimes = crimeLab.getCrimes(); + if(this.adapter == null) { + adapter = new CrimeAdapter(crimes); + crimeRecyclerView.setAdapter(adapter); + } + else { + adapter.setCrimes(crimes); + adapter.notifyDataSetChanged(); + } + updateSubtitle(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + View view = + inflater.inflate(R.layout.fragment_crime_list, + container, false); + crimeRecyclerView = (RecyclerView) view + .findViewById(R.id.crime_recycler_view); + crimeRecyclerView.setLayoutManager( + new LinearLayoutManager(getActivity())); + + if (savedInstanceState != null) { + subtitleVisible = + savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE); + } + + updateUI(); + return view; + } + + @Override + public void onResume() { + super.onResume(); + updateUI(); + } + + @Override + public void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + outState.putBoolean(SAVED_SUBTITLE_VISIBLE, + subtitleVisible); + } + + //CRIME HOLDER + private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ + private Crime crime; + private TextView titleTextView; + private TextView dateTextView; + private ImageView solvedImageView; + public void bind(Crime crime){ + this.crime = crime; + titleTextView.setText(this.crime.getTitle()); + dateTextView.setText(this.crime.getDate().toString()); + solvedImageView.setVisibility(crime.isSolved() ? View.VISIBLE : View.GONE); + } + 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); + solvedImageView =itemView.findViewById(R.id.imageView_green_cross); + } + + @Override + public void onClick(View v) { + //CHAPTER10 +// Intent intent = CrimeActivity.newIntent(getActivity(), +// crime.getId()); + + //CHAPTER11 + Intent intent = + CrimePagerActivity.newIntent(getActivity(), + crime.getId()); + startActivity(intent); + + } + //CHAPTER8 +// Intent intent = new Intent(getActivity(), CrimeActivity.class); +// startActivity(intent); +// Toast.makeText(getActivity(), +// this.crime.getTitle() + " clicked!", +// Toast.LENGTH_SHORT) +// .show(); + + } + //ADAPTER + private class CrimeAdapter extends RecyclerView.Adapter{ + private List crimes; + + public CrimeAdapter(List crimes) { + this.crimes = 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 = crimes.get(position); + holder.bind(crime); + } + + @Override + public int getItemCount() { + return crimes.size(); + } + + public void setCrimes(List whatCrimes) { + crimes = whatCrimes; + } + + } + + @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 (subtitleVisible) { + subtitleItem.setTitle(R.string.hide_subtitle); + } else { + subtitleItem.setTitle(R.string.show_subtitle); + } + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == R.id.new_crime) { + Crime crime = new Crime(); + + CrimeLab.get(getActivity()).addCrime(crime); + Intent intent = CrimePagerActivity + .newIntent(getActivity(), + crime.getId()); + startActivity(intent); + return true; + } + else if(item.getItemId() == R.id.show_subtitle) + { + subtitleVisible = !subtitleVisible; + getActivity().invalidateOptionsMenu(); + updateSubtitle(); + return true; + } + else + return super.onOptionsItemSelected(item); + } + +} diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimePagerActivity.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimePagerActivity.java new file mode 100644 index 0000000..4a6dcea --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/CrimePagerActivity.java @@ -0,0 +1,70 @@ +package asdv.lisset.criminalintent; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import java.util.List; +import java.util.UUID; +//Chapter 11 +public class CrimePagerActivity extends AppCompatActivity { + + private ViewPager viewPager; + private List crimes; + public static final String EXTRA_CRIME_ID = + "com.bignerdranch.android.criminalintent.crime_id"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_crime_pager); + + + UUID crimeId = (UUID) getIntent() + .getSerializableExtra(EXTRA_CRIME_ID); + + viewPager = (ViewPager)findViewById(R.id.crime_view_pager); + crimes = CrimeLab.get(this).getCrimes(); + FragmentManager fragmentManager = getSupportFragmentManager(); + viewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) { + @Override + public Fragment getItem(int position) + { + Crime crime = crimes.get(position); + return + CrimeFragment.newInstance(crime.getId()); + } + @Override + public int getCount() { + return crimes.size(); + } + }); + //to select proper crime instead of default first crime + for (int i = 0; i < crimes.size(); i++) { + if + (crimes.get(i).getId().equals(crimeId)) { + viewPager.setCurrentItem(i); + break; } + } + + + } + + public static Intent newIntent(Context + packageContext, UUID crimeId) { + Intent intent = new Intent(packageContext, + CrimePagerActivity.class); + intent.putExtra(EXTRA_CRIME_ID, crimeId); + return intent; + } +} diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/DatePickerFragment.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/DatePickerFragment.java new file mode 100644 index 0000000..587db57 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/DatePickerFragment.java @@ -0,0 +1,87 @@ +package asdv.lisset.criminalintent; + +import android.app.Activity; +import android.app.AlertDialog; +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.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"; + private DatePicker mDatePicker; + + public static final String EXTRA_DATE = "com.bignerdranch.android.criminalintent.date"; + public static DatePickerFragment newInstance(Date date) + { + Bundle args = new Bundle(); + args.putSerializable(ARG_DATE, date); + DatePickerFragment fragment = new DatePickerFragment(); + fragment.setArguments(args); + return fragment; + } + + private void sendResult(int resultCode, Date date) + { + //Gets Target Fragment here from CrimeFragment + if (getTargetFragment() == null) + { + return; + } + Intent intent = new Intent(); + intent.putExtra(EXTRA_DATE, date); + getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent); + } + + + @Override + public Dialog onCreateDialog(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); + calendar.setTimeInMillis(500); + + View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_date, null); + + mDatePicker = (DatePicker) + v.findViewById(R.id.dialog_date_picker); + mDatePicker.init(year, month, day, null); + + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder = builder.setTitle(R.string.date_picker_title); + builder = builder.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); + } + }); + builder = builder.setView(v); + return builder.create(); + + //return new AlertDialog.Builder(getActivity()).setTitle(R.string.date_picker_title) + // .setPositiveButton(android.R.string.ok,null).create(); + } + +} diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/SingleFragmentActivity.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/SingleFragmentActivity.java new file mode 100644 index 0000000..585d634 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/SingleFragmentActivity.java @@ -0,0 +1,28 @@ +package asdv.lisset.criminalintent; + +import android.os.Bundle; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +public abstract class SingleFragmentActivity extends AppCompatActivity { + protected abstract Fragment createFragment(); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_fragment); + FragmentManager fm = + getSupportFragmentManager(); + Fragment fragment = + fm.findFragmentById(R.id.fragment_container); + if (fragment == null) { + fragment = createFragment(); + fm.beginTransaction().add( + R.id.fragment_container, fragment).commit(); + } + } +} diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/TimePickerFragment.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/TimePickerFragment.java new file mode 100644 index 0000000..3fdd7f1 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/TimePickerFragment.java @@ -0,0 +1,84 @@ +package asdv.lisset.criminalintent; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.DatePicker; +import android.widget.TimePicker; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +public class TimePickerFragment extends DialogFragment +{ private static final String ARG_TIME = "time"; + private TimePicker mTimePicker; + + public static final String EXTRA_TIME = "com.bignerdranch.android.criminalintent.time"; + + public static TimePickerFragment newInstance(Date time) { + Bundle args = new Bundle(); + args.putSerializable(ARG_TIME, time); + TimePickerFragment fragment = new TimePickerFragment(); + fragment.setArguments(args); + return fragment; + } + + private void sendResult(int resultCode, Date time) { + if (getTargetFragment() == null) { + return; + } + Intent intent = new Intent(); + intent.putExtra(EXTRA_TIME, time); + getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_time, null); + + mTimePicker = v.findViewById(R.id.dialog_time_picker); +// mTimePicker.setIs24HourView(false); // Set to 12-hour format + + Date date = (Date) getArguments().getSerializable(ARG_TIME); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + // Set the initial time in the TimePicker + mTimePicker.setCurrentHour(calendar.get(Calendar.HOUR_OF_DAY)); // Set current hour + mTimePicker.setCurrentMinute(calendar.get(Calendar.MINUTE)); // Set current minute + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.time_picker_title) + .setView(v) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + int hour = mTimePicker.getCurrentHour(); + int minute = mTimePicker.getCurrentMinute(); + + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minute); + + Date time = calendar.getTime(); + sendResult(Activity.RESULT_OK, time); + } + }); + return builder.create(); + } + +} diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeBaseHelper.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeBaseHelper.java new file mode 100644 index 0000000..8dd9252 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeBaseHelper.java @@ -0,0 +1,30 @@ +package asdv.lisset.criminalintent.database; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import asdv.lisset.criminalintent.database.CrimeDbSchema; + +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) { + String executionString = "create table " + CrimeDbSchema.CrimeTable.NAME; + executionString += " _id integer primary key autoincrement" + + CrimeDbSchema.CrimeTable.Cols.UUID + ", " + + CrimeDbSchema.CrimeTable.Cols.TITLE + ", " + + CrimeDbSchema.CrimeTable.Cols.DATE + ", " + + CrimeDbSchema.CrimeTable.Cols.SOLVED; + db.execSQL(executionString); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } +} diff --git a/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeCursorWrapper.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeCursorWrapper.java new file mode 100644 index 0000000..8572afd --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeCursorWrapper.java @@ -0,0 +1,32 @@ +package asdv.lisset.criminalintent.database; + +import android.database.Cursor; +import android.database.CursorWrapper; + +import java.util.Date; +import java.util.UUID; + +import asdv.lisset.criminalintent.Crime; + +public class CrimeCursorWrapper extends CursorWrapper { + public CrimeCursorWrapper(Cursor cursor) { + super(cursor); + } + public Crime getCrime() { + String uuidString = + getString(getColumnIndex(CrimeDbSchema.CrimeTable.Cols.UUID)); + String title = + getString(getColumnIndex(CrimeDbSchema.CrimeTable.Cols.TITLE)); + long date = + getLong(getColumnIndex(CrimeDbSchema.CrimeTable.Cols.DATE)); + int isSolved = + getInt(getColumnIndex(CrimeDbSchema.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/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeDbSchema.java b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeDbSchema.java new file mode 100644 index 0000000..e222bb5 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/java/asdv/lisset/criminalintent/database/CrimeDbSchema.java @@ -0,0 +1,15 @@ +package asdv.lisset.criminalintent.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/Assignments/CriminalIntent13/app/src/main/res/drawable-anydpi/ic_menu_add.xml b/Assignments/CriminalIntent13/app/src/main/res/drawable-anydpi/ic_menu_add.xml new file mode 100644 index 0000000..672478e --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/res/drawable-anydpi/ic_menu_add.xml @@ -0,0 +1,11 @@ + + + diff --git a/Assignments/CriminalIntent13/app/src/main/res/drawable-hdpi/ic_menu_add.png b/Assignments/CriminalIntent13/app/src/main/res/drawable-hdpi/ic_menu_add.png new file mode 100644 index 0000000..8707b00 Binary files /dev/null and b/Assignments/CriminalIntent13/app/src/main/res/drawable-hdpi/ic_menu_add.png differ diff --git a/Assignments/CriminalIntent13/app/src/main/res/drawable-mdpi/ic_menu_add.png b/Assignments/CriminalIntent13/app/src/main/res/drawable-mdpi/ic_menu_add.png new file mode 100644 index 0000000..c0fb2bb Binary files /dev/null and b/Assignments/CriminalIntent13/app/src/main/res/drawable-mdpi/ic_menu_add.png differ diff --git a/Assignments/CriminalIntent13/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/Assignments/CriminalIntent13/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Assignments/CriminalIntent13/app/src/main/res/drawable-xhdpi/ic_menu_add.png b/Assignments/CriminalIntent13/app/src/main/res/drawable-xhdpi/ic_menu_add.png new file mode 100644 index 0000000..6eedadf Binary files /dev/null and b/Assignments/CriminalIntent13/app/src/main/res/drawable-xhdpi/ic_menu_add.png differ diff --git a/Assignments/CriminalIntent13/app/src/main/res/drawable-xxhdpi/ic_menu_add.png b/Assignments/CriminalIntent13/app/src/main/res/drawable-xxhdpi/ic_menu_add.png new file mode 100644 index 0000000..7a27534 Binary files /dev/null and b/Assignments/CriminalIntent13/app/src/main/res/drawable-xxhdpi/ic_menu_add.png differ diff --git a/Assignments/CriminalIntent13/app/src/main/res/drawable/ic_launcher_background.xml b/Assignments/CriminalIntent13/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Assignments/CriminalIntent13/app/src/main/res/layout-land/fragment_crime.xml b/Assignments/CriminalIntent13/app/src/main/res/layout-land/fragment_crime.xml new file mode 100644 index 0000000..f9d51ff --- /dev/null +++ b/Assignments/CriminalIntent13/app/src/main/res/layout-land/fragment_crime.xml @@ -0,0 +1,51 @@ + + + + + + + + + + +