从另一个片段调用一个片段的方法(或者获得下一个/ prev ID)
我有一个应用程序设置,遵循Udacity课程的轮廓。有一个MainActivity和DetailActivity,都带有片段。 “主”侧查询MediaStore.Images.Thumbnails并显示GridView中的所有大拇指。单击时,将使用IMAGE_ID
构造URI,并启动DetailActivity。这显示全尺寸图像+一些元数据。从另一个片段调用一个片段的方法(或者获得下一个/ prev ID)
我现在想知道如何在我的详细用户界面中制作“prev”和“next”按钮。点击这些将在详细用户界面中打开相应的(prev或下一个)图像。从技术上讲,这意味着使用更新的URI刷新ContentLoader。我只需要一些方法来获取上一个和下一个IMAGE_ID。
我想我可以在detailfragment内做到这一切“本地”,说做一个查询来获取下一个ID:
SELECT MIN(IMAGE_ID) NEXT_ID FROM thumbnails WHERE IMAGE_ID > ? ORDER BY DATE DESC;
,我想在目前IMAGE_ID
作为参数插件。然后我可以构建新的URI,并重新启动加载程序。对?我不得不弄清楚如何实现这个作为查询内容解析器,但我想这样的可能可以完成。
但是,MainActivity处理onClick,它首先将我带到DetailActivity(thumb - >图像)。它知道GridView的int mPosition
,甚至是。只是要求MainActivity(或MainFragment)为我提供prev/next ID,不是一个更好的解决方案吗?但接下来的问题是,我如何从DetailFragment的MainFragment中调用一个方法?我是否通过片段管理器,像这样?
Fragment mainfrag = getActivity().getFragmentManager().findFragmentByTag("MainFragment");
而且是正确的获得上/下一个ID是这样的:
int prevId = mPosition-1;
int nextId = mPosition+1;
更新:我尝试添加一个标签给每个片段,并用段管理得到参考PhotoFragment(来自DetailFragment),但当我这样做时我总是收到
null
:
PhotoFragment pf = (PhotoFragment) getActivity().getSupportFragmentManager().findFragmentByTag(PHOTOFRAGMENT_TAG); int position = pf.getPosition(); // crash: pf == null
这是因为,在一部手机上,细节活动/片段代替的主要活动,阻止它?正如你可以在MainActivity中看到的,下面我在一个更大的屏幕上有一个双窗格UI,但是(在平板电脑上)有ClassCastException:
java.lang.ClassCastException:com.example.android.galleri。 app.DetailFragment不能转换为com.example.android.galleri.app.PhotoFragment
无论如何,这里是我的项目大纲。我如何从DetailFragment调用PhotoFragment ...
MainActivitypublic class MainActivity extends ActionBarActivity implements PhotoFragment.Callback {
private static final String DETAILFRAGMENT_TAG = "DFTAG";
private boolean mTwoPane;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.photo_detail_container) != null) {
mTwoPane = true;
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.photo_detail_container, new DetailFragment(), DETAILFRAGMENT_TAG)
.commit();
}
} else {
mTwoPane = false;
}
}
@Override
public void onItemSelected(Uri contentUri) {
if (mTwoPane) {
Bundle args = new Bundle();
args.putParcelable(DetailFragment.DETAIL_URI, contentUri);
DetailFragment fragment = new DetailFragment();
fragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.photo_detail_container, fragment, DETAILFRAGMENT_TAG)
.commit();
} else {
// launch DetailActivity
Intent intent = new Intent(this, DetailActivity.class)
.setData(contentUri);
startActivity(intent);
}
}
}
光碎片(“主片段)
import com.example.android.galleri.app.data.PhotoContract;
public class PhotoFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
private final static int LOADER_ID = 87;
private PhotoAdapter mPhotoAdapter;
private int mPosition;
private GridView mGridView;
private TextView mEmptyView;
private int count_mem = -1;
private static final String SELECTED_KEY = "POSITION";
// these are the data we want from MediaStore
private final static String[] THUMBNAIL_COLUMNS = {
PhotoContract.ThumbEntry.COLUMN_THUMB_ID,
PhotoContract.ThumbEntry.COLUMN_DATA,
PhotoContract.ThumbEntry.COLUMN_IMAGE_ID
};
static final int COL_THUMB_ID = 0;
static final int COL_THUMB_DATA = 1;
static final int COL_THUMB_IMAGE_ID = 2;
// interfaces
public interface Callback {
public void onItemSelected(Uri photoUri);
}
public PhotoFragment() {
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
getLoaderManager().initLoader(LOADER_ID, null, this);
super.onActivityCreated(savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState) {
if (mPosition != GridView.INVALID_POSITION) {
outState.putInt(SELECTED_KEY, mPosition);
}
super.onSaveInstanceState(outState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
mPhotoAdapter = new PhotoAdapter(getActivity(), null, 0);
GridView gridView = (GridView) rootView.findViewById(R.id.listview_photo);
gridView.setAdapter(mPhotoAdapter);
mEmptyView = (TextView) rootView.findViewById(R.id.list_empty);
mGridView = gridView;
// handle user clicking on an image
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Cursor cursor = (Cursor) parent.getItemAtPosition(position);
if (cursor != null) {
Uri baseUri = PhotoContract.PhotoEntry.buildPhotoUriWithId(cursor.getLong(COL_THUMB_IMAGE_ID));
((Callback)getActivity()).onItemSelected(baseUri);
}
mPosition = position;
}
});
if (savedInstanceState != null && savedInstanceState.containsKey(SELECTED_KEY)) {
mPosition = savedInstanceState.getInt(SELECTED_KEY);
}
return rootView;
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
Uri thumbs_uri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
return new CursorLoader(getActivity(), thumbs_uri, THUMBNAIL_COLUMNS,
null,null, // read everything (all thumbnails)
MediaStore.Images.Thumbnails._ID + " DESC");
}
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
int antall = 0;
if (cursor != null) {
antall = cursor.getCount();
// register observer onto cursor
cursor.setNotificationUri(getActivity().getContentResolver(), MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI);
mPhotoAdapter.swapCursor(cursor);
if (mPosition != GridView.INVALID_POSITION) {
mGridView.setSelection(mPosition); // scroll into view
}
}
}
@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
mPhotoAdapter.swapCursor(null);
}
}
DetailActivity
public class DetailActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
if (savedInstanceState == null) {
Bundle arguments = new Bundle();
arguments.putParcelable(DetailFragment.DETAIL_URI, getIntent().getData());
DetailFragment fragment = new DetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.add(R.id.photo_detail_container, fragment)
.commit();
}
}
}
DetailFragment
import com.example.android.galleri.app.data.PhotoContract;
public class DetailFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
static final String DETAIL_URI = "URI";
private static final int DETAIL_LOADER = 0;
private ImageView mPhotoView;
private Long mImageID;
private static final String[] DETAIL_COLUMNS = {
PhotoContract.PhotoEntry.COLUMN_IMAGE_ID,
PhotoContract.PhotoEntry.COLUMN_DISPLAY_NAME,
PhotoContract.PhotoEntry.COLUMN_DATA,
PhotoContract.PhotoEntry.COLUMN_DESC,
PhotoContract.PhotoEntry.COLUMN_DATE_TAKEN,
PhotoContract.PhotoEntry.COLUMN_DATE_ADDED,
PhotoContract.PhotoEntry.COLUMN_TITLE,
PhotoContract.PhotoEntry.COLUMN_SIZE,
PhotoContract.PhotoEntry.COLUMN_ORIENTATION,
PhotoContract.PhotoEntry.COLUMN_HEIGHT,
PhotoContract.PhotoEntry.COLUMN_WIDTH
};
static final int COL_IMAGE_ID = 0;
static final int COL_DISPLAY_NAME = 1;
static final int COL_DATA = 2;
static final int COL_DESC = 3;
static final int COL_DATE_TAKEN = 4;
static final int COL_DATE_ADDED = 5;
static final int COL_TITLE = 6;
static final int COL_SIZE = 7;
static final int COL_ORIENTATION = 8;
static final int COL_HEIGHT = 9;
static final int COL_WIDTH = 10;
private Uri mUri;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle arguments = getArguments();
if (arguments != null) {
mUri = arguments.getParcelable(DetailFragment.DETAIL_URI);
}
// get ID from URI
if (mUri != null) {
mImageID = PhotoContract.PhotoEntry.getImageIdFromUri(mUri);
}
View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
mPhotoView = (ImageView) rootView.findViewById(R.id.pic_frame);
return rootView;
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
if (mUri != null) {
return new CursorLoader(getActivity(),
mUri, // URI passed in
DETAIL_COLUMNS, null, null, null);
}
return null;
}
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data) {
if (!data.moveToFirst()) {
return;
}
String thumbData = data.getString(COL_DATA);
Bitmap thumbBitmap = BitmapFactory.decodeFile(thumbData);
mPhotoView.setImageBitmap(thumbBitmap);
}
@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
getLoaderManager().initLoader(DETAIL_LOADER, null, this);
super.onActivityCreated(savedInstanceState);
}
}
在手机上,这不起作用。当用户启动DetailActivity
时,MainActivity
不会继续在“后台”中运行。因此,为了坚持数据,我创建了一个新类,Utility
,它保存光标和最后一次点击的位置 - 这两个都设置为PhotoFragment
(即从MainActivity
)。然后,DetailFragment
可以从Utility
获取光标和位置。似乎工作:)
import android.database.Cursor;
public class Utility {
private static Cursor mCursor;
private static int mPosition;
public static void setCursor(Cursor cursor) {
mCursor = cursor;
}
public static Cursor getCursor() {
return mCursor;
}
public static void setPosition(int position) {
mPosition = position;
}
public static int getPosition() {
return mPosition;
}
}