105-Android Studio 1.5 Master Detail Activity Template
2.2) res/layout/activity_item_list
2.3.1) res/layout/item_list.xml
2.3.2) res/layout/item_list.xml (w900dp)
2.4) Detail Controller (Java) Files
2.4.1) ItemDetailActivity.java
2.4.2) ItemDetailFragment.java
Continue from Tutorial 104 |
Application Name: MyMasterDetail1
Company Domain: notarazi.com
Package Name: com.notarazi.mymasterdetail1 (auto-generated)
Project Location: C:\Project1\MyMasterDetail1\ (auto-generated)
Select Master/Detail Flow.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.notarazi.mymasterdetail1"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".ItemListActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ItemDetailActivity" android:label="@string/title_item_detail" android:parentActivityName=".ItemListActivity" android:theme="@style/AppTheme.NoActionBar"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.notarazi.mymasterdetail1.ItemListActivity" /> </activity> </application> </manifest> |
package com.notarazi.mymasterdetail1; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.notarazi.mymasterdetail1.dummy.DummyContent; import java.util.List; /** * An activity representing a list of Items. This activity * has different presentations for handset and tablet-size devices. On * handsets, the activity presents a list of items, which when touched, * lead to a {@link ItemDetailActivity} representing * item details. On tablets, the activity presents the list of items and * item details side-by-side using two vertical panes. */ public class ItemListActivity extends AppCompatActivity { /** * Whether or not the activity is in two-pane mode, i.e. running on a tablet * device. */ private boolean mTwoPane; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_item_list); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); toolbar.setTitle(getTitle()); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); View recyclerView = findViewById(R.id.item_list); assert recyclerView != null; setupRecyclerView((RecyclerView) recyclerView); if (findViewById(R.id.item_detail_container) != null) { // The detail container view will be present only in the // large-screen layouts (res/values-w900dp). // If this view is present, then the // activity should be in two-pane mode. mTwoPane = true; } } private void setupRecyclerView(@NonNull RecyclerView recyclerView) { recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(DummyContent.ITEMS)); } public class SimpleItemRecyclerViewAdapter extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> { private final List<DummyContent.DummyItem> mValues; public SimpleItemRecyclerViewAdapter(List<DummyContent.DummyItem> items) { mValues = items; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_list_content, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(final ViewHolder holder, int position) { holder.mItem = mValues.get(position); holder.mIdView.setText(mValues.get(position).id); holder.mContentView.setText(mValues.get(position).content); holder.mView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mTwoPane) { Bundle arguments = new Bundle(); arguments.putString(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id); ItemDetailFragment fragment = new ItemDetailFragment(); fragment.setArguments(arguments); getSupportFragmentManager().beginTransaction() .replace(R.id.item_detail_container, fragment) .commit(); } else { Context context = v.getContext(); Intent intent = new Intent(context, ItemDetailActivity.class); intent.putExtra(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id); context.startActivity(intent); } } }); } @Override public int getItemCount() { return mValues.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public final View mView; public final TextView mIdView; public final TextView mContentView; public DummyContent.DummyItem mItem; public ViewHolder(View view) { super(view); mView = view; mIdView = (TextView) view.findViewById(R.id.id); mContentView = (TextView) view.findViewById(R.id.content); } @Override public String toString() { return super.toString() + " '" + mContentView.getText() + "'"; } } } } |
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".MainActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/frameLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <include layout="@layout/item_list" /> </FrameLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout> |
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.RecyclerView 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/item_list" android:name="com.notarazi.mymasterdetail1.ItemListFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" app:layoutManager="LinearLayoutManager" tools:context="com.notarazi.mymasterdetail1.ItemListActivity" tools:listitem="@layout/item_list_content" /> |
<LinearLayout 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:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:baselineAligned="false" android:divider="?android:attr/dividerHorizontal" android:orientation="horizontal" android:showDividers="middle" tools:context="com.notarazi.mymasterdetail1.ItemListActivity"> <!-- This layout is a two-pane layout for the Items master/detail flow.
--> <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/item_list" android:name="com.notarazi.mymasterdetail1.ItemListFragment" android:layout_width="@dimen/item_width" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" app:layoutManager="LinearLayoutManager" tools:context="com.notarazi.mymasterdetail1.ItemListActivity" tools:listitem="@layout/item_list_content" /> <FrameLayout android:id="@+id/item_detail_container" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" /> </LinearLayout> |
How do we create layout variation file? Right-click layout item in the Project Explorer, select New/Layout Resource File... Type layout-w...dp in the Directory name. |
package com.notarazi.mymasterdetail1; import android.content.Intent; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.widget.Toolbar; import android.view.View; import android.support.v7.app.AppCompatActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.NavUtils; import android.view.MenuItem; /** * An activity representing a single Item detail screen. This * activity is only used narrow width devices. On tablet-size devices, * item details are presented side-by-side with a list of items * in a {@link ItemListActivity}. */ public class ItemDetailActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_item_detail); Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own detail action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); // Show the Up button in the action bar. ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); } // savedInstanceState is non-null when there is fragment state // saved from previous configurations of this activity // (e.g. when rotating the screen from portrait to landscape). // In this case, the fragment will automatically be re-added // to its container so we don't need to manually add it. // For more information, see the Fragments API guide at: // // http://developer.android.com/guide/components/fragments.html // if (savedInstanceState == null) { // Create the detail fragment and add it to the activity // using a fragment transaction. Bundle arguments = new Bundle(); arguments.putString(ItemDetailFragment.ARG_ITEM_ID, getIntent().getStringExtra(ItemDetailFragment.ARG_ITEM_ID)); ItemDetailFragment fragment = new ItemDetailFragment(); fragment.setArguments(arguments); getSupportFragmentManager().beginTransaction() .add(R.id.item_detail_container, fragment) .commit(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == android.R.id.home) { // This ID represents the Home or Up button. In the case of this // activity, the Up button is shown. Use NavUtils to allow users // to navigate up one level in the application structure. For // more details, see the Navigation pattern on Android Design: // // http://developer.android.com/design/patterns/navigation.html#up-vs-back // NavUtils.navigateUpTo(this, new Intent(this, ItemListActivity.class)); return true; } return super.onOptionsItemSelected(item); } } |
package com.notarazi.mymasterdetail1; import android.app.Activity; import android.support.design.widget.CollapsingToolbarLayout; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.notarazi.mymasterdetail1.dummy.DummyContent; /** * A fragment representing a single Item detail screen. * This fragment is either contained in a {@link ItemListActivity} * in two-pane mode (on tablets) or a {@link ItemDetailActivity} * on handsets. */ public class ItemDetailFragment extends Fragment { /** * The fragment argument representing the item ID that this fragment * represents. */ public static final String ARG_ITEM_ID = "item_id"; /** * The dummy content this fragment is presenting. */ private DummyContent.DummyItem mItem; /** * Mandatory empty constructor for the fragment manager to instantiate the * fragment (e.g. upon screen orientation changes). */ public ItemDetailFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments().containsKey(ARG_ITEM_ID)) { // Load the dummy content specified by the fragment // arguments. In a real-world scenario, use a Loader // to load content from a content provider. mItem = DummyContent.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID)); Activity activity = this.getActivity(); CollapsingToolbarLayout appBarLayout = (CollapsingToolbarLayout) activity.findViewById(R.id.toolbar_layout); if (appBarLayout != null) { appBarLayout.setTitle(mItem.content); } } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.item_detail, container, false); // Show the dummy content as text in a TextView. if (mItem != null) { ((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.details); } return rootView; } } |