Crime.java
package com.example.aster.criminalintent;
import java.util.Date;
import java.util.UUID;
public class Crime {
private UUID mId;
private String mTitle;
private Date mDate;
private boolean mSolved;
public Crime () {
mId = UUID.randomUUID();
mDate = new Date();
}
public UUID getId () {
return mId;
}
public String getTitle () {
return mTitle;
}
public void setTitle (String title) {
mTitle = title;
}
public Date getDate () {
return mDate;
}
public void setDate (Date date) {
mDate = date;
}
public boolean isSolved () {
return mSolved;
}
public void setSolved (boolean solved) {
mSolved = solved;
}
}
CrimeFragment.java
package com.example.aster.criminalintent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
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 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 Crime mCrime;
private EditText mTitleField;
private Button mDateButton;
private CheckBox mSolvedCheckBox;
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 (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 v = inflater.inflate(R.layout.fragment_crime, container, false );
mTitleField = (EditText) v.findViewById(R.id.crime_title);
mTitleField.setText(mCrime.getTitle());
mTitleField.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) {
}
});
mDateButton = (Button) v.findViewById(R.id.crime_date);
mDateButton.setText(mCrime.getDate().toString());
mDateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick (View v) {
FragmentManager manager = getFragmentManager();
DatePickerFragment dialog = DatePickerFragment
.newInstance(mCrime.getDate());
dialog.show(manager, DIALOG_DATE);
}
});
mSolvedCheckBox = (CheckBox) v.findViewById(R.id.crime_solved);
mSolvedCheckBox.setChecked(mCrime.isSolved());
mSolvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged (CompoundButton buttonView, boolean isChecked) {
mCrime.setSolved(isChecked);
}
});
return v;
}
}
CrimeLab.java
package com.example.aster.criminalintent;
import android.content.Context;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class CrimeLab {
private static CrimeLab sCrimeLab;
private List<Crime> mCrimes;
public static CrimeLab get (Context context) {
if (sCrimeLab == null ) {
sCrimeLab = new CrimeLab(context);
}
return sCrimeLab;
}
private CrimeLab (Context context) {
mCrimes = new ArrayList<>();
for (int i = 0 ; i < 100 ; i++) {
Crime crime = new Crime();
crime.setTitle("Crime #" + i);
crime.setSolved(i % 2 == 0 );
mCrimes.add(crime);
}
}
public List<Crime> getCrimes () {
return mCrimes;
}
public Crime getCrime (UUID id) {
for (Crime crime : mCrimes) {
if (crime.getId().equals(id)) {
return crime;
}
}
return null ;
}
}
CrimeListActivity.java
package com.example.aster.criminalintent;
import android.support.v4.app.Fragment;
public class CrimeListActivity extends SingleFragmentActivity {
@Override
protected Fragment createFragment () {
return new CrimeListFragment();
}
}
CrimeListFragment.java
package com.example.aster.criminalintent;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class CrimeListFragment extends Fragment {
private RecyclerView mCrimeRecyclerView;
private CrimeAdapter mAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container , Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_crime_list, container , false );
mCrimeRecyclerView = (RecyclerView) view.findViewById(R.id.crime_recycler_view);
mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
@Override
public void onResume() {
super .onResume();
updateUI();
}
private void updateUI() {
CrimeLab crimeLab = CrimeLab.get(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
if (mAdapter == null ) {
mAdapter = new CrimeAdapter(crimes);
mCrimeRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.notifyDataSetChanged();
}
}
private class CrimeHolder extends RecyclerView .ViewHolder
implements View .OnClickListener {
private Crime mCrime;
private TextView mTitleTextView;
private TextView mDateTextView;
private ImageView mSolvedImageView;
public CrimeHolder(LayoutInflater inflater, ViewGroup parent) {
super (inflater.inflate(R.layout.list_item_crime, parent, false ));
itemView.setOnClickListener(this );
mTitleTextView = (TextView) itemView.findViewById(R.id.crime_title);
mDateTextView = (TextView) itemView.findViewById(R.id.crime_date);
mSolvedImageView = (ImageView) itemView.findViewById(R.id.crime_solved);
}
public void bind(Crime crime) {
mCrime = crime;
mTitleTextView.setText(mCrime.getTitle());
mDateTextView.setText(mCrime.getDate().toString());
mSolvedImageView.setVisibility(crime.isSolved() ? View.VISIBLE : View.GONE);
}
@Override
public void onClick(View view) {
Intent intent = CrimePagerActivity.newIntent(getActivity(), mCrime.getId());
startActivity(intent);
}
}
private class CrimeAdapter extends RecyclerView .Adapter <CrimeHolder > {
private List<Crime> mCrimes;
public CrimeAdapter(List<Crime> crimes) {
mCrimes = crimes;
}
@Override
public CrimeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
return new CrimeHolder(layoutInflater, parent);
}
@Override
public void onBindViewHolder(CrimeHolder holder, int position) {
Crime crime = mCrimes.get(position);
holder.bind(crime);
}
@Override
public int getItemCount() {
return mCrimes.size();
}
}
}
package com.example.aster.criminalintent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import java.util.List;
import java.util.UUID;
public class CrimePagerActivity extends AppCompatActivity {
private static final String EXTRA_CRIME_ID =
"com.example.aster.criminalintent.crime_id" ;
private ViewPager mViewPager;
private List<Crime> 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 (Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_crime_pager);
UUID crimeId = (UUID) getIntent()
.getSerializableExtra(EXTRA_CRIME_ID);
mViewPager = (ViewPager) findViewById(R.id.crime_view_pager);
mCrimes = CrimeLab.get(this ).getCrimes();
FragmentManager fragmentManager = getSupportFragmentManager();
mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
@Override
public Fragment getItem (int position) {
Crime crime = mCrimes.get(position);
return CrimeFragment.newInstance(crime.getId());
}
@Override
public int getCount () {
return mCrimes.size();
}
});
for (int i = 0 ; i < mCrimes.size(); i++) {
if (mCrimes.get(i).getId().equals(crimeId)) {
mViewPager.setCurrentItem(i);
break ;
}
}
}
}
DatePickerFragment.java
package com .example .aster .criminalintent
import android.app .Dialog
import android.os .Bundle
import android.support .v 4.app .DialogFragment
import android.support .v 7.app .AlertDialog
import android.view .LayoutInflater
import android.view .View
import android.widget .DatePicker
import java.util .Calendar
import java.util .Date
public class DatePickerFragment extends DialogFragment {
private static final String ARG_DATE = "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
}
@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)
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)
return new AlertDialog.Builder (getActivity())
.setView (v)
.setTitle (R.string .date _picker_title)
.setPositiveButton (android.R .string .ok , null)
.create ()
}
}
SingleFragmentActivity.java
package com.example.aster.criminalintent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
public abstract class SingleFragmentActivity extends AppCompatActivity {
protected abstract Fragment createFragment ();
@Override
protected void onCreate (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();
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android ="http://schemas.android.com/apk/res/android"
package ="com.example.aster.criminalintent" >
<application
android:allowBackup ="true"
android:icon ="@mipmap/ic_launcher"
android:label ="@string/app_name"
android:roundIcon ="@mipmap/ic_launcher_round"
android:supportsRtl ="true"
android:theme ="@style/AppTheme" >
<activity android:name =".CrimeListActivity" >
<intent-filter >
<action android:name ="android.intent.action.MAIN" />
<category android:name ="android.intent.category.LAUNCHER" />
</intent-filter >
</activity >
<activity android:name =".CrimePagerActivity" >
</activity >
</application >
</manifest >
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android ="http://schemas.android.com/apk/res/android"
android:id ="@+id/crime_view_pager"
android:layout_width ="match_parent"
android:layout_height ="match_parent" >
</android.support.v4.view.ViewPager >
activity_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android ="http://schemas.android.com/apk/res/android"
android:id ="@+id/fragment_container"
android:layout_width ="match_parent"
android:layout_height ="match_parent" />
dialog_date.xml
<?xml version="1.0" encoding="utf-8"?>
<DatePicker
xmlns:android ="http://schemas.android.com/apk/res/android"
android:id ="@+id/dialog_date_picker"
android:layout_width ="wrap_content"
android:layout_height ="wrap_content"
android:calendarViewShown ="false" >
</DatePicker >
fragment_crime.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android ="http://schemas.android.com/apk/res/android"
android:layout_width ="match_parent"
android:layout_height ="match_parent"
android:layout_margin ="16dp"
android:orientation ="vertical" >
<TextView
style ="?android:listSeparatorTextViewStyle"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:text ="@string/crime_title_label" />
<EditText
android:id ="@+id/crime_title"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:hint ="@string/crime_title_hint" />
<TextView
style ="?android:listSeparatorTextViewStyle"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:text ="@string/crime_details_label" />
<Button
android:id ="@+id/crime_date"
android:layout_width ="match_parent"
android:layout_height ="wrap_content" />
<CheckBox
android:id ="@+id/crime_solved"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:text ="@string/crime_solved_label" />
</LinearLayout >
fragment_crime_list.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android ="http://schemas.android.com/apk/res/android"
android:id ="@+id/crime_recycler_view"
android:layout_width ="match_parent"
android:layout_height ="match_parent" />
list_item_crime.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android"
xmlns:app ="http://schemas.android.com/apk/res-auto"
xmlns:tools ="http://schemas.android.com/tools"
android:id ="@+id/linearLayout"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
tools:layout_editor_absoluteY ="81dp" >
<TextView
android:id ="@+id/crime_title"
android:layout_width ="0dp"
android:layout_height ="wrap_content"
android:layout_marginEnd ="8dp"
android:layout_marginStart ="16dp"
android:layout_marginTop ="16dp"
android:text ="Crime Title"
app:layout_constraintEnd_toStartOf ="@+id/crime_solved"
app:layout_constraintStart_toStartOf ="parent"
app:layout_constraintTop_toTopOf ="parent" />
<TextView
android:id ="@+id/crime_date"
android:layout_width ="0dp"
android:layout_height ="wrap_content"
android:layout_marginEnd ="8dp"
android:layout_marginStart ="16dp"
android:layout_marginTop ="8dp"
android:text ="Crime Date"
app:layout_constraintEnd_toStartOf ="@+id/crime_solved"
app:layout_constraintStart_toStartOf ="parent"
app:layout_constraintTop_toBottomOf ="@+id/crime_title" />
<ImageView
android:id ="@+id/crime_solved"
android:layout_width ="wrap_content"
android:layout_height ="wrap_content"
android:layout_marginBottom ="16dp"
android:layout_marginEnd ="16dp"
android:layout_marginTop ="16dp"
app:layout_constraintBottom_toBottomOf ="parent"
app:layout_constraintEnd_toEndOf ="parent"
app:layout_constraintTop_toTopOf ="parent"
app:srcCompat ="@drawable/ic_solved" />
</android.support.constraint.ConstraintLayout >
strings.xml
<resources>
<string name ="app_name" >CriminalIntent</string >
<string name ="crime_title_hint" >Enter a title for the crime.</string >
<string name ="crime_title_label" >Title</string >
<string name ="crime_details_label" >Details</string >
<string name ="crime_solved_label" >Solved</string >
<string name ="date_picker_title" >Date of crime:</string >
</resources>