Android 从另一个片段调用一个片段中的方法(或者,获取下一个/上一个ID)
我已经按照Udacity课程的大纲安装了一个应用程序。有MainActivity和DetailActivity,都带有片段。“主”端查询MediaStore.Images.Thumbnails并在GridView中显示所有缩略图。单击时,将使用Android 从另一个片段调用一个片段中的方法(或者,获取下一个/上一个ID),android,user-interface,gridview,imageview,Android,User Interface,Gridview,Imageview,我已经按照Udacity课程的大纲安装了一个应用程序。有MainActivity和DetailActivity,都带有片段。“主”端查询MediaStore.Images.Thumbnails并在GridView中显示所有缩略图。单击时,将使用图像\u ID构造URI,并启动DetailActivity。这显示了完整大小的图像+一些元数据 我现在想知道如何在我的详细界面中创建“prev”和“next”按钮。单击这些将在详细信息UI中打开相应的(上一个或下一个)图像。从技术上讲,这意味着使用更新的
图像\u ID
构造URI,并启动DetailActivity。这显示了完整大小的图像+一些元数据
我现在想知道如何在我的详细界面中创建“prev”和“next”按钮。单击这些将在详细信息UI中打开相应的(上一个或下一个)图像。从技术上讲,这意味着使用更新的URI刷新ContentLoader。我只是需要一些方法来获得上一个和下一个图像的ID
我想我可以在detailfragment中“本地”完成这一切,比如通过查询获取下一个ID:
SELECT MIN(IMAGE_ID) NEXT_ID FROM thumbnails WHERE IMAGE_ID > ? ORDER BY DATE DESC;
在这里,我将插入当前的IMAGE\u ID
作为参数。然后我可以构造新的URI,并重新启动加载程序。对吗?我必须弄清楚如何将其实现为对内容解析器的查询,但我想类似的事情是可以做到的
然而,main活动处理onClick,它首先将我带到DetailActivity(thumb->image)。它甚至知道GridView的整数组合。让MainActivity(或MainFragment)给我上一个/下一个ID不是更好的解决方案吗?但问题是,如何从DetailFragment调用MainFragment中的方法?我要通过碎片管理器吗,像这样的
Fragment mainfrag = getActivity().getFragmentManager().findFragmentByTag("MainFragment");
这样获取上一个/下一个ID是否正确:
int prevId = mPosition-1;
int nextId = mPosition+1;
更新:我尝试为每个片段添加一个标记,并使用片段管理器(从DetailFragment)获取对PhotoFragment的引用,但当我执行以下操作时,我一直得到null
:
PhotoFragment pf=(PhotoFragment)getActivity().getSupportFragmentManager().findFragmentByTag(PhotoFragment_标记);
int position=pf.getPosition();//崩溃:pf==null
这是因为在手机上,细节活动/片段替换了主活动,从而停止了它吗?正如您在下面的MainActivity中所看到的,我在一个更大的屏幕上有一个两个窗格的UI,但在那里(平板电脑上),我得到了一个ClassCastException:
java.lang.ClassCastException:com.example.android.galleri.app.DetailFragment无法强制转换为com.example.android.galleri.app.PhotoFragment
无论如何,这是我的项目大纲。如何从DetailFragment调用PhotoFragment
主要活动
照片片段(“主要片段”)
细节片段
import com.example.android.galleri.app.data.PhotoContract;
公共类DetailFragment扩展片段实现LoaderManager.LoaderCallbacks{
静态最终字符串详细信息\u URI=“URI”;
私有静态最终整数细节加载程序=0;
私有图像视图mPhotoView;
私人长图像;
私有静态最终字符串[]详细信息\列={
PhotoContract.PhotoEntry.COLUMN\u IMAGE\u ID,
PhotoContract.PhotoEntry.COLUMN\u DISPLAY\u NAME,
PhotoContract.PhotoEntry.COLUMN_数据,
PhotoContract.PhotoEntry.COLUMN_DESC,
PhotoContract.PhotoEntry.COLUMN\u日期,
添加了PhotoContract.PhotoEntry.COLUMN\u DATE\u,
PhotoContract.PhotoEntry.COLUMN_标题,
PhotoContract.PhotoEntry.COLUMN\u尺寸,
光合同.光条目.柱方向,
PhotoContract.PhotoEntry.COLUMN\u高度,
PhotoContract.PhotoEntry.COLUMN\u宽度
};
静态最终int COL_IMAGE_ID=0;
静态最终整数列显示名称=1;
静态最终整数列数据=2;
静态最终整数列描述=3;
静态最终整数列日期=4;
静态最终整数列添加日期=5;
静态最终整数列标题=6;
静态最终整数列大小=7;
静态最终内柱方向=8;
静态最终内柱高度=9;
静态最终内柱宽度=10;
私有Uri mUri;
@凌驾
CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态){
Bundle arguments=getArguments();
if(参数!=null){
mUri=arguments.getParcelable(DetailFragment.DETAIL\u URI);
}
//从URI获取ID
如果(mUri!=null){
mImageID=PhotoContract.PhotoEntry.getImageIdFromUri(mUri);
}
视图根视图=充气机。充气(R.layout.fragment\u详细信息,容器,错误);
mPhotoView=(ImageView)rootView.findviewbyd(R.id.pic_frame);
返回rootView;
}
@凌驾
公共加载器onCreateLoader(int-id,Bundle-args){
如果(mUri!=null){
返回新的游标装入器(getActivity(),
mUri,//传入了URI
详细信息_列,空,空,空);
}
返回null;
}
@凌驾
公共void onLoadFinished(加载器游标加载器,游标数据){
如果(!data.moveToFirst()){
返回;
}
String thumbData=data.getString(COL_data);
位图thumbBitmap=BitmapFactory.decodeFile(thumbData);
设置图像位图(拇指位图);
}
@凌驾
public void onLoaderReset(加载器游标加载器){
}
@凌驾
已创建ActivityState上的公共无效(Bundle savedInstanceState){
getLoaderManager().initLoader(详细信息加载程序,null,this);
super.onActivityCreated(savedInstanceState);
}
}
在手机上,这不起作用。当用户启动DetailActivity
时,MainActivity
不会“在后台”继续运行。因此,为了保存数据,我创建了一个新类,实用程序
,它保存光标和最后一次单击的位置——这两个都是从PhotoFragment
设置的(即从MainActivity
)。然后,DetailFragment
可以从实用程序
获取光标和位置。似乎可以工作:)
public 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);
}
}
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();
}
}
}
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);
}
}
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;
}
}