- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我尝试将一个简单的基于 Activity 的应用程序移植到 fragment 中已经整整一周了。我完全卡住了。
这个野兽是一个简单的列表、详细信息、添加/编辑应用程序,带有上下文菜单和选项菜单。我试图做到正确: fragment 和 Activity 各自在自己的文件中,使用手机和平板电脑的 v4 支持包, fragment 完成了可重用 fragment 应该做的一切,回调(很多)飞来飞去通知 Activity 和关于该做什么的 fragment 。从 SQLiteOpenHelper 转换为 ContentProvider,从 optionmenu 转换为 actionbarmenu,以及,和,以及,……(我使用的几乎所有内容现在都已弃用)。
太可怕了。我的基于 Activity 的简单小型工作应用程序现在的大小几乎是原来的 3 倍,而且很多东西还不能正常工作。
如果需要,我可以在此处添加我的代码 - 但它有很多东西(您已被警告)。
我的问题:是否有人愿意分享一个包含列表、详细信息和添加/编辑的完整示例?此示例应为 Fragments 和 Activity 使用单独的文件(而不是来自 Google 的一体化包)。
请不要投反对票。我真的很想看看如何使它正确。
非常感谢。
编辑:
这是开始 Activity ,它有两种布局(res/layout 用于手机,res/layout-large-land 用于平板电脑)和上下文菜单:
public class ActivityList extends FragmentActivity implements FragmentList.MyContextItemSelectedListener,
FragmentList.MyDeleteListener,
FragmentList.MyListItemClickListener,
FragmentList.MyOptionsItemSelectedListener,
FragmentDetails.MyDeleteListener,
FragmentDetails.MyOptionsItemSelectedListener {
@Override
public void myContextItemSelected(final int action, final long id) {
if (action == R.id.men_add) {
processEdit(0);
} else if (action == R.id.men_delete) {
processUpdateList();
} else if (action == R.id.men_details) {
processDetails(id);
} else if (action == R.id.men_edit) {
processEdit(id);
}
}
@Override
public void myDelete(final long id) {
processUpdateList();
}
@Override
public void myListItemClick(final long id) {
processDetails(id);
}
@Override
public void myOptionsItemSelected(final int action) {
myOptionsItemSelected(action, 0);
}
@Override
public void myOptionsItemSelected(final int action, final long id) {
if (action == R.id.men_add) {
processEdit(0);
} else if (action == R.id.men_edit) {
processEdit(id);
} else if (action == R.id.men_preferences) {
processPreferences();
}
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
processUpdateList();
}
@Override
public void onCreate(final Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activitylist);
}
private void processEdit(final long id) {
Intent intent = new Intent(this, ActivityEdit.class);
intent.putExtra("ID", id);
startActivityForResult(intent, MyConstants.DLG_TABLE1EDIT);
}
private void processDetails(final long id) {
if (Tools.isXlargeLand(getApplicationContext())) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.right);
if (fragment == null ||
(fragment instanceof FragmentDetails && ((FragmentDetails) fragment).getCurrentId() != id)) {
fragment = new FragmentDetails(id);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.right, fragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.commit();
}
} else {
Intent intent = new Intent(this, ActivityDetails.class);
intent.putExtra("ID", id);
startActivityForResult(intent, MyConstants.DLG_TABLE1SHOW);
}
}
private void processPreferences() {
Intent intent = new Intent(this, MyPreferenceActivity.class);
startActivityForResult(intent, MyConstants.DLG_PREFERENCES);
}
private void processUpdateList() {
// TODO:
}
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
class="com.test.app.FragmentList"
android:id="@+id/fragmentlist"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:name="com.test.app.FragmentList" />
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
class="com.test.app.FragmentList"
android:id="@+id/fragmentlist"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_width="0dip"
android:name="com.test.app.FragmentList" />
<FrameLayout
android:id="@+id/right"
android:layout_height="match_parent"
android:layout_weight="2"
android:layout_width="0dip" />
</LinearLayout>
这是带有行布局、选项菜单和上下文菜单的 ListFragment:
public class FragmentList extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
private SimpleCursorAdapter adapter;
private AlertDialog alertDialog;
private Context context;
private MyContextItemSelectedListener contextItemSelectedListener;
private MyDeleteListener deleteListener;
private long id;
private MyListItemClickListener listItemClickListener;
private ListView listView;
private MyOptionsItemSelectedListener optionsItemSelectedListener;
public interface MyContextItemSelectedListener {
public void myContextItemSelected(int action, long id);
}
public interface MyDeleteListener {
public void myDelete(long id);
}
public interface MyListItemClickListener {
public void myListItemClick(long id);
}
public interface MyOptionsItemSelectedListener {
public void myOptionsItemSelected(int action);
}
@Override
public void onActivityCreated(final Bundle bundle) {
super.onActivityCreated(bundle);
context = getActivity().getApplicationContext();
listView = getListView();
getActivity().getSupportLoaderManager().initLoader(MyConstants.LDR_TABLE1LIST, null, this);
adapter = new SimpleCursorAdapter(context,
R.layout.fragmentlist_row,
null,
new String[] { Table1.DESCRIPTION },
new int[] { R.id.fragmentlist_row_description },
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(adapter);
setListShown(false);
registerForContextMenu(listView);
if (bundle != null && bundle.containsKey("ID")) {
id = bundle.getLong("ID");
listItemClickListener.myListItemClick(id);
}
if (Tools.isXlargeLand(context)) {
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
setHasOptionsMenu(true);
}
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
// Reduced: Check for implemented listeners
}
@Override
public boolean onContextItemSelected(final MenuItem menuItem) {
AdapterContextMenuInfo adapterContextMenuInfo = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
final long id = adapterContextMenuInfo.id;
if (menuItem.getItemId() == R.id.men_delete) {
processAlertDialog(id);
return true;
} else {
contextItemSelectedListener.myContextItemSelected(menuItem.getItemId(), adapterContextMenuInfo.id);
}
return super.onContextItemSelected(menuItem);
}
@Override
public void onCreateContextMenu(final ContextMenu contextMenu, final View view, final ContextMenuInfo contextMenuInfo) {
super.onCreateContextMenu(contextMenu, view, contextMenuInfo);
if (view.getId() == android.R.id.list) {
getActivity().getMenuInflater().inflate(R.menu.fragmentlist_context, contextMenu);
}
}
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle bundle) {
MyCursorLoader loader = null;
switch (id) {
case MyConstants.LDR_TABLE1LIST:
loader = new MyCursorLoader(context,
MySQLiteOpenHelper.TABLE1_FETCH,
null);
break;
}
return loader;
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater menuInflater) {
super.onCreateOptionsMenu(menu, menuInflater);
menu.clear();
menuInflater.inflate(R.menu.fragmentlist, menu);
}
@Override
public void onListItemClick(final ListView listView, final View view, final int position, final long id) {
super.onListItemClick(listView, view, position, id);
this.id = id;
if (Tools.isXlargeLand(context)) {
listView.setItemChecked(position, true);
}
listItemClickListener.myListItemClick(id);
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
adapter.swapCursor(null);
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor cursor) {
adapter.swapCursor(cursor);
setListShown(true);
}
@Override
public boolean onOptionsItemSelected(final MenuItem menuItem) {
optionsItemSelectedListener.myOptionsItemSelected(menuItem.getItemId());
return super.onOptionsItemSelected(menuItem);
}
@Override
public void onSaveInstanceState(final Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putLong("ID", id);
}
private void processAlertDialog(final long id) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int which) {
dialogInterface.dismiss();
}
} );
alertDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int which) {
MyApplication.getSqliteOpenHelper().deleteTable1(id);
alertDialog.dismiss();
deleteListener.myDelete(id);
}
} );
alertDialogBuilder.setCancelable(false);
alertDialogBuilder.setMessage(R.string.txt_reallydelete);
alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:paddingBottom="2dip"
android:paddingTop="2dip" >
<TextView
style="@style/TextViewLarge"
android:id="@+id/fragmentlist_row_description"
android:textStyle="bold" />
</LinearLayout>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:icon="@drawable/ic_menu_add"
android:id="@+id/men_add"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_add" />
<item
android:icon="@drawable/ic_menu_preferences"
android:id="@+id/men_preferences"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_preferences" />
</menu>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/men_details"
android:title="@string/txt_details" />
<item
android:id="@+id/men_edit"
android:title="@string/txt_edit" />
<item
android:id="@+id/men_delete"
android:title="@string/txt_delete" />
</menu>
这是 DetailsActivity:
public class ActivityDetails extends FragmentActivity implements FragmentDetails.MyDeleteListener,
FragmentDetails.MyOptionsItemSelectedListener {
private long id;
@Override
public void myDelete(final long id) {
setResult(RESULT_OK);
finish();
}
@Override
public void myOptionsItemSelected(final int action, final long id) {
if (action == R.id.men_add) {
processEdit(0);
} else if (action == R.id.men_edit) {
processEdit(id);
} else if (action == R.id.men_preferences) {
processPreferences();
}
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
if (requestCode == MyConstants.DLG_PREFERENCES || requestCode == MyConstants.DLG_TABLE1EDIT) {
finish();
startActivity(getIntent());
}
}
@Override
protected void onCreate(final Bundle bundle) {
super.onCreate(bundle);
if (bundle != null) {
if (bundle.containsKey("ID")) {
id = bundle.getLong("ID");
}
} else {
Bundle bundleExtras = getIntent().getExtras();
if (bundleExtras != null) {
id = bundleExtras.getLong("ID");
}
processDetails(id);
}
}
@Override
public void onSaveInstanceState(final Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putLong("ID", id);
}
private void processDetails(final long id) {
FragmentDetails fragment = new FragmentDetails(id);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(android.R.id.content, fragment);
transaction.commit();
}
private void processEdit(final long id) {
Intent intent = new Intent(this, ActivityEdit.class);
intent.putExtra("ID", id);
startActivityForResult(intent, MyConstants.DLG_TABLE1EDIT);
}
private void processPreferences() {
Intent intent = new Intent(this, MyPreferenceActivity.class);
startActivityForResult(intent, MyConstants.DLG_PREFERENCES);
}
}
这是带有布局和菜单的 DetailsFragment:
public class FragmentDetails extends Fragment {
private AlertDialog alertDialog;
private MyDeleteListener deleteListener;
private long id;
private MyOptionsItemSelectedListener optionsItemSelectedListener;
private TextView textViewDescription;
private TextView textViewId;
public FragmentDetails() {
id = 0;
}
public FragmentDetails(final long id) {
this.id = id;
}
public long getCurrentId() {
return id;
}
public interface MyDeleteListener {
public void myDelete(long id);
}
public interface MyOptionsItemSelectedListener {
public void myOptionsItemSelected(int action, long id);
}
@Override
public void onActivityCreated(final Bundle bundle) {
super.onActivityCreated(bundle);
if (bundle != null && bundle.containsKey("ID")) {
id = bundle.getLong("ID");
}
setHasOptionsMenu(true);
}
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
// Reduced
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater menuInflater) {
super.onCreateOptionsMenu(menu, menuInflater);
menu.clear();
menuInflater.inflate(R.menu.fragmentdetails, menu);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup viewGroup, final Bundle bundle) {
View view = inflater.inflate(R.layout.fragmentdetails, null);
textViewDescription = (TextView) view.findViewById(R.id.tv_description);
textViewId = (TextView) view.findViewById(R.id.tv_id);
if (id != 0) {
Table1 table1;
if ((table1 = MyApplication.getSqliteOpenHelper().getTable1(id)) != null) {
textViewDescription.setText(Tools.defaultString(table1.getDescription()));
textViewId.setText(Tools.defaultString(String.valueOf(table1.getId())));
}
}
return view;
}
@Override
public boolean onOptionsItemSelected(final MenuItem menuItem) {
if (menuItem.getItemId() == R.id.men_delete) {
processAlertDialog(id);
return true;
} else {
optionsItemSelectedListener.myOptionsItemSelected(menuItem.getItemId(), id);
}
return super.onOptionsItemSelected(menuItem);
}
@Override
public void onSaveInstanceState(final Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putLong("ID", id);
}
private void processAlertDialog(final long id) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int which) {
alertDialog.dismiss();
alertDialog = null;
}
} );
alertDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int which) {
MyApplication.getSqliteOpenHelper().deleteTable1(id);
alertDialog.dismiss();
alertDialog = null;
deleteListener.myDelete(id);
}
} );
alertDialogBuilder.setCancelable(false);
alertDialogBuilder.setMessage(R.string.txt_reallydelete);
alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal" >
<TextView
style="@style/TextViewStandard"
android:layout_weight="1"
android:text="@string/txt_id" />
<TextView
style="@style/TextViewStandard"
android:id="@+id/tv_id"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal" >
<TextView
style="@style/TextViewStandard"
android:layout_weight="1"
android:text="@string/txt_description" />
<TextView
style="@style/TextViewStandard"
android:id="@+id/tv_description"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:icon="@drawable/ic_menu_add"
android:id="@+id/men_add"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_add" />
<item
android:icon="@drawable/ic_menu_edit"
android:id="@+id/men_edit"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_edit" />
<item
android:icon="@drawable/ic_menu_delete"
android:id="@+id/men_delete"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_delete" />
<item
android:icon="@drawable/ic_menu_preferences"
android:id="@+id/men_preferences"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_preferences" />
</menu>
我没有发布 EditActivity,因为它只是一个没有 Fragment 的 FragmentActivity。
最佳答案
这可能不是全部答案,而是部分答案:您仍然有一个主要 Activity ,在您曾经有 ListView 的 xml 中,您现在添加了一个框架布局。然后在您的 oncreate Activity 中添加以下内容:
mMainFragment = new ListFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.center_container, mMainFragment);
fragmentTransaction.commit();
mCurrentFragment = mMainFragment;
在你的列表 fragment 中
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// setup view
View view = inflater.inflate(R.layout.calendar_list, null);
mListAdapter = new CustomAdapter(getActivity(), R.layout.calendar_row, (ArrayList<Item>) mFullList);
setListAdapter(mListAdapter);
return view;
}
列表 fragment 的 XML:
<somelayout>
<ListView android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</somelayout>
点击列表在 fragment 中触发:
@Override
public void onListItemClick(ListView list, View view, int position, long id) {
final Item item = (Item) list.getAdapter().getItem(position);
mListener.OnListClick(item);
}
它使用这个监听器:
公共(public)接口(interface) OnListItemClickListener { public void OnListClick(Item item);
Listfragment 需要将其置于顶部:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnListItemClickListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnListItemClickListener");
}
}
然后主 Activity 通过实现接口(interface)订阅此内容,并在触发监听器时启动详细信息 fragment 。
编辑:好的,所以你的问题要基本得多:)记住 oncreate 每次旋转时都会在你的 Activity 中调用,所以你的 Activity 需要记住要显示哪个 fragment ,就像它需要记住要显示哪个 View 一样。您还需要将 fragment 添加到返回堆栈,否则返回键将无法使用它们。将 fragment 视为具有功能的 View ,它们不是 Activity 。
关于android - 坚持从 Activity 移植到 fragment ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10013023/
我对 Android 很陌生,如果问题重复,请避免并发送链接。有三个 Activity A、B 和 C。 Activity A 获取一个用户名,我想在 Activity C 中显示该用户名,但我想先运
我正在尝试制作记事本应用程序,因此每次打开新笔记时,布局都会相同。另外, Activity 的数量(新注释)不应定义得尽可能多 最佳答案 如果 Activity 始终相同,您可能应该创建一个适配器,允
我有 3 个 Activity 。 主窗口 5 个按钮 在按钮的主窗口中按下此窗口打开(将其称为父窗口) 在父窗口按钮上按下此窗口打开调用它作为结束子窗口。 现在从子窗口我从父窗口获取值如下:
我遇到了一个 Activity backstack 问题。假设我的后台有 5 个 Activity :比如 Activity A、 Activity B、 Activity C、 Activity D
我正在寻找必须具有以下附加特征的 JMS 提供程序: 采用多代理,所有代理都必须处于事件状态(无单点故障) 仅在两台机器上进行扩展就足以满足我们的需求 能够保证订购(如果 1 个生产者 + 1 个消费
假设,我有一个由 TabHost 组成的选项卡 Activity 。 TabHost 包含 2 个选项卡,每两个选项卡都有一个 Activity 组。每个 Activity 组包含一项 Activit
我正在开发一个应用程序,我需要根据某些操作导航到特定 Activity 。这是一张图片 我的第一个 Activity 是 ReadingActivity。基于某些操作,用户将被带到 NewProjec
我创建了一个与服务器异步通信的应用程序。当应用程序发出服务器请求时,将创建一个带有“正在加载”通知的新对话框( Activity )。主要 Activity 实现了处理服务器响应的方法,我想在主要 A
我想在我的所有应用程序 Activity 中显示相同的选项菜单。我创建了一个实现菜单的通用 Activity ,并且我所有的进一步 Activity 都扩展了它。 问题:当我需要扩展其他特定 Acti
我有四个 Activity ,即 java 文件 - Activity1.java、activity2.java、activity3.java、activity4.java 和 xml 文件 - Ac
我有两个 Activity 。我想将数据从第二个 Activity 发送到上一个 Activity 。第一个 Activity 有自定义 ListView 和 bean 类。当我点击第二个 Activ
根 Activity 是堆栈中当前的第一个 Activity 还是 list 中指定为启动 Activity 的 Activity ? 支持应用程序 P 在启动时启动 Activity A。然后 A
你好 我想知道您在绘制 Activity 图选择“Activity ”时考虑了哪些关键点? 您如何从要建模的问题中选择 Activity ? 谢谢 最佳答案 Activity 图用于对正在开发的系统和
如何从主 Activity 启动 Activity 并在子 Activity 返回主 Activity 中退出操作后返回主 Activity ? 我已将子 Activity 作为启动器 Intent
我的工作流程如下: 登录 Activity -> ActivityB -> ActivityC -> ActivityD 我想将数据从LoginActivity传递到ActivityD,但不直接传递到
我之前曾尝试获得此问题的答案,但找不到可以解决我的问题的答案。我正在制作保存圆盘高尔夫球分数的应用程序。我的 MainActivity 有 4 个按钮。新比赛、恢复比赛、类(class)和球员。 At
我有一个 tts 非 UI 类和 Activity 类。现在在 Activity 类中,我有一个按钮,用户可以从中选择男声或女声,具体取决于我想要将字符串传递给 tts 类的选择,然后一次tts 类根
问题有点复杂,首先, Activity A 和 Activity B 的 list 中都有 android:noHistory = true 。我有一个自定义 serialized 类,假设 MyCl
在我的应用程序中,我有两个 Activity (AuthenticationActivity 和 MainActivity),每个 Activity 都有一个导航图和大量 fragment 。我创建了
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: How can i use compose email activity in tabView? 我想在选项
我是一名优秀的程序员,十分优秀!