創建列表明細應用1-使用fragment
阿新 • • 發佈:2017-09-30
line aps idg 展示 closed public 裏來 androidm 權威指南
筆記自《Android編程權威指南第二版》
第七章,創建一個列表明細應用
fragment是一種控制器對象,activity可委派它完成一些任務,這些任務通常就是管理用戶界面。(管理用戶界面的fragment又稱UI fragment。它自己也產生布局文件)
利用fragment,可輕松實現選擇不同的列表項就顯示對應的明細視圖Activity負責以一個明細fragment替換另一個明細fragment
托管可以這樣理解,activity在其視圖層級裏提供一處位置來放置fragment的視圖。fragment本身不具有在屏幕上顯示視圖的能力。
添加支持庫:
dependencies {compile fileTree(include: [‘*.jar‘], dir: ‘libs‘)
androidTestCompile(‘com.android.support.test.espresso:espresso-core:2.2.2‘, {
exclude group: ‘com.android.support‘, module: ‘support-annotations‘
})
compile ‘com.android.support:appcompat-v7:26.+‘
compile ‘com.android.support.constraint:constraint-layout:1.0.0-alpha8‘testCompile ‘junit:junit:4.12‘
compile ‘com.android.support:support-v4:26.0.0-alpha1‘
compile ‘com.android.support:recyclerview-v7:26.0.0-alpha1‘
}
項目結構:
Crime實體類:
package com.homelink.testcriminal; import java.util.Date; import java.util.UUID; /** * Created by ysc on 2017/9/30.View Code*/ 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; } }
SingleFragmentActivity抽象基類,用於CrimeActivity , CrimeListActivity。而這兩個Activity又分別創建各自的Fragment
package com.homelink.testcriminal; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; /** * Created by ysc on 2017/9/30. */ public abstract class SingleFragmentActivity extends FragmentActivity { protected abstract Fragment createFragment(); @Override public 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(); } } }View Code
CrimeActitiy.java
package com.homelink.testcriminal; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.os.Bundle; public class CrimeActivity extends SingleFragmentActivity { @Override protected Fragment createFragment() { return new CrimeFragment(); } }View Code
CrimeListActivity.java
package com.homelink.testcriminal; import android.support.v4.app.Fragment; /** * Created by ysc on 2017/9/30. */ public class CrimeListActivity extends SingleFragmentActivity { @Override protected Fragment createFragment() { return new CrimeListFragment(); } }View Code
activity_fragment.xml 的layout,用於托管fragment。很簡單,就只放了一個FrameLayout,用於承載Fragment
<?xml version="1.0" encoding="utf-8"?> <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" tools:context="com.homelink.testcriminal.CrimeActivity"> <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" /> </LinearLayout>View Code
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="wrap_content" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/crime_title_label" style="?android:listSeparatorTextViewStyle" /> <EditText android:id="@+id/crime_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:hint="@string/crime_title_hint" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/crime_details_label" style="?android:listSeparatorTextViewStyle" /> <Button android:id="@+id/crime_date" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" /> <CheckBox android:id="@+id/crime_solved" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:text="@string/crime_solved_label" /> </LinearLayout>View Code
橫向:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/crime_title_label" style="?android:listSeparatorTextViewStyle" /> <EditText android:id="@+id/crime_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:hint="@string/crime_title_hint" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/crime_details_label" style="?android:listSeparatorTextViewStyle" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" > <Button android:id="@+id/crime_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> <CheckBox android:id="@+id/crime_solved" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/crime_solved_label" /> </LinearLayout> </LinearLayout>View Code
CrimeFragment.java控制器,展示數據
package com.homelink.testcriminal; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; 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.EditText; /** * Created by ysc on 2017/9/30. */ public class CrimeFragment extends Fragment { private Crime mCrime; private EditText mTitleField; private Button mDateButton; private CheckBox mSolvedCheckBox; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCrime = new Crime(); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_crime, container, false); mTitleField = (EditText)v.findViewById(R.id.crime_title); mTitleField.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged( CharSequence s, int start, int count, int after) { // This space intentionally left blank } @Override public void onTextChanged( CharSequence s, int start, int before, int count) { mCrime.setTitle(s.toString()); } @Override public void afterTextChanged(Editable s) { // This one too } }); mDateButton = (Button)v.findViewById(R.id.crime_date); mDateButton.setText(mCrime.getDate().toString()); mDateButton.setEnabled(false); return v; } }View Code
列表項的控制CrimeListFragment.java:
package com.homelink.testcriminal; import android.os.Bundle; 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.CheckBox; import android.widget.TextView; import android.widget.Toast; import java.util.List; /** * Created by ysc on 2017/9/30. */ public class CrimeListFragment extends Fragment { private RecyclerView mCrimeRecyclerView; @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; } private CrimeAdapter mAdapter; private void updateUI() { CrimeLab crimeLab = CrimeLab.get(getActivity()); List<Crime> crimes = crimeLab.getCrimes(); mAdapter = new CrimeAdapter(crimes); mCrimeRecyclerView.setAdapter(mAdapter); } private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener { private Crime mCrime; private TextView mTitleTextView; private TextView mDateTextView; private CheckBox mSolvedCheckBox; public CrimeHolder(View itemView) { super(itemView); itemView.setOnClickListener(this); mTitleTextView = (TextView) itemView.findViewById(R.id.list_item_crime_title_text_view); mDateTextView = (TextView) itemView.findViewById(R.id.list_item_crime_date_text_view); mSolvedCheckBox = (CheckBox)itemView.findViewById(R.id.list_item_crime_solved_check_box); } public void BindCrime(Crime crime){ mCrime = crime; mTitleTextView.setText(mCrime.getTitle()); mDateTextView.setText(mCrime.getDate().toString()); mSolvedCheckBox.setChecked(mCrime.isSolved()); } @Override public void onClick(View view) { Toast.makeText(getActivity(), mCrime.getTitle() + " clicked!", Toast.LENGTH_SHORT).show(); } } 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()); View view = layoutInflater.inflate(R.layout.list_item_crime, parent, false); return new CrimeHolder(view); } @Override public void onBindViewHolder(CrimeHolder holder, int position) { Crime crime = mCrimes.get(position); //holder.mTitleTextView.setText(crime.getTitle()); holder.BindCrime(crime); } @Override public int getItemCount() { return mCrimes.size(); } } }View Code
數據從哪裏來,單例的CrimeLab.java
package com.homelink.testcriminal; import android.content.Context; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * Created by ysc on 2017/9/30. */ public class CrimeLab { private static CrimeLab sCrimeLab; public static CrimeLab get(Context context) { if (sCrimeLab == null) { sCrimeLab = new CrimeLab(context); } return sCrimeLab; } private CrimeLab(Context context) { initCrimes(); } private List<Crime> mCrimes; private void initCrimes(){ mCrimes = new ArrayList<>(); for (int i = 0; i < 100; i++) { Crime crime = new Crime(); crime.setTitle("Crime #" + i); crime.setSolved(i % 2 == 0); // Every other one 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; } }View Code
如果是顯示列表呢,使用recyclerview,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"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content"> <CheckBox android:id="@+id/list_item_crime_solved_check_box" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:padding="4dp"/> <TextView android:id="@+id/list_item_crime_title_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toLeftOf="@id/list_item_crime_solved_check_box" android:textStyle="bold" android:padding="4dp" tools:text="Crime Title"/> <TextView android:id="@+id/list_item_crime_date_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toLeftOf="@id/list_item_crime_solved_check_box" android:layout_below="@id/list_item_crime_title_text_view" android:padding="4dp" tools:text="Crime Date"/> </RelativeLayout>View Code
當然先修改一下AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.homelink.testcriminal">
<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=".CrimeActivity">
</activity>
</application>
</manifest>
運行:
創建列表明細應用1-使用fragment