CrimeBaseHelper.java
package com.example.aster.criminalintent.database.CrimeDbSchema;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.example.aster.criminalintent.Crime;
import com.example.aster.criminalintent.database.CrimeDbSchema.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) {
}
}
CrimeCursorWrapper.java
package com .example .aster .criminalintent .database .CrimeDbSchema
import android.database .Cursor
import android.database .CursorWrapper
import com .example .aster .criminalintent .Crime
import java.util .Date
import java.util .UUID
import static com .example .aster .criminalintent .database .CrimeDbSchema .CrimeDbSchema .*
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
}
}
CrimeDbSchema
package com.example.aster.criminalintent.database.CrimeDbSchema;
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" ;
}
}
}
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 () {
this (UUID.randomUUID());
}
public Crime (UUID id) {
mId = id;
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.app.Activity;
import android.content.Intent;
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.text.DateFormat;
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 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 void onPause () {
super .onPause();
CrimeLab.get(getActivity())
.updateCrime(mCrime);
}
@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);
updateDate();
mDateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick (View v) {
FragmentManager manager = getFragmentManager();
DatePickerFragment dialog = DatePickerFragment
.newInstance(mCrime.getDate());
dialog.setTargetFragment(CrimeFragment.this , REQUEST_DATE);
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;
}
@Override
public void onActivityResult (int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
return ;
}
if (requestCode == REQUEST_DATE) {
Date date = (Date) data
.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
mCrime.setDate(date);
updateDate();
}
}
private void updateDate () {
mDateButton.setText(mCrime.getDate().toString());
}
private String getCrimeReport () {
String solvedString = null ;
if (mCrime.isSolved()) {
solvedString = getString(R.string.crime_report_solved);
} else {
solvedString = getString(R.string.crime_report_unsolved);
}
String dateFormat = "EEE, MMM dd" ;
String dateString = android.text.format.DateFormat.format(dateFormat, mCrime.getDate()).toString();
String suspect = mCrime.getSuspect();
if (suspect == null ) {
suspect = getString(R.string.crime_report_no_suspect);
} else {
suspect = getString(R.string.crime_report_suspect, suspect);
}
String report = getString(R.string.crime_report,
mCrime.getTitle(), dateString, solvedString, suspect);
return report;
}
}
CrimeLab.java
package com .example .aster .criminalintent
import android.content .ContentValues
import android.content .Context
import android.database .Cursor
import android.database .sqlite .SQLiteDatabase
import com .example .aster .criminalintent .database .CrimeDbSchema .CrimeBaseHelper
import com .example .aster .criminalintent .database .CrimeDbSchema .CrimeCursorWrapper
import com .example .aster .criminalintent .database .CrimeDbSchema .CrimeDbSchema
import java.util .ArrayList
import java.util .List
import java.util .UUID
import static com .example .aster .criminalintent .database .CrimeDbSchema .CrimeDbSchema .*
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 c) {
ContentValues values = getContentValues(c)
mDatabase.insert (CrimeTable.NAME , null, values)
}
public List<Crime> getCrimes() {
List<Crime> 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.getId ().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.getId ().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
}
}
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.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
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 java.util.List;
public class CrimeListFragment extends Fragment {
private static final String SAVED_SUBTITLE_VISIBLE = "subtitle" ;
private RecyclerView mCrimeRecyclerView;
private CrimeAdapter mAdapter;
private boolean mSubtitleVisible;
@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 );
mCrimeRecyclerView = (RecyclerView) view.findViewById(R.id.crime_recycler_view);
mCrimeRecyclerView.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 (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_SUBTITLE_VISIBLE, mSubtitleVisible);
}
@Override
public void onCreateOptionsMenu (Menu menu, 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 (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 .subtitlt_format, crimeCount);
if (!mSubtitleVisible) {
subtitle = null ;
}
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.getSupportActionBar().setSubtitle(subtitle);
}
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.setCrimes(crimes);
mAdapter.notifyDataSetChanged();
}
updateSubtitle();
}
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();
}
public void setCrimes (List<Crime> crimes) {
mCrimes = crimes;
}
}
}
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.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class DatePickerFragment extends DialogFragment {
public static final String EXTRA_DATE =
"com.example.aster.criminalintent.date" ;
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,
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);
}
}
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"
android:parentActivityName =".CrimeListActivity" >
</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" />
<Button
android:id ="@+id/crime_suspect"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:text ="@string/crime_suspect_text" />
<Button
android:id ="@+id/crime_report"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:text ="@string/crime_report_text" />
</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" />
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android ="http://schemas.android.com/apk/res/android"
xmlns:app ="http://schemas.android.com/apk/res-auto" >
<item
android:id ="@+id/new_crime"
android:icon ="@drawable/ic_menu_add"
android:title ="@string/new_crime"
app:showAsAction ="ifRoom|withText" />
<item
android:id ="@+id/show_subtitle"
android:title ="@string/show_subtitle"
app:showAsAction ="ifRoom" />
</menu >
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 >
<string name ="new_crime" >New Crime</string >
<string name ="show_subtitle" >Show Subtitle</string >
<string name ="hide_subtitle" >Hide Subtitle</string >
<string name ="subtitle_format" >%1 $d crimes</string >
<string name ="crime_suspect_text" >Choose Suspect</string >
<string name ="crime_report_text" >Send Crime Report</string >
<string name ="crime_report" >%1 $s!
The crime was discovered on %2 $s. %3 $s, %4 $s</string >
<string name ="crime_report_solved" >The case is solved</string >
<string name ="crime_report_unsolved" >The case is not solved</string >
<string name ="crime_report_no_suspect" >there is no suspect.</string >
<string name ="crime_report_suspect" >the suspect is %s.</string >
<string name ="crime_report_subject" >CriminalIntent Crime Report</string >
<string name ="send_report" >Send crime report via</string >
</resources>