从另一个片段调用一个片段的方法(或者获得下一个/ 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 ...

MainActivity
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); 
    } 

} 

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; 
    } 
}