我有一个视图寻呼机,其中每个页面都是一个自定义视图(...而不是 a Fragment
),我使用LayoutInflator
. 每个自定义视图都有一个ImageView
内部,使用该Glide
库填充来自网络的图像。
我的任务是当用户滚动时,每次他更改页面时都会抛出视图寻呼机,我需要检索Bitmap
正在填充当前显示的页面ImageView
。
我尝试OnPageChangeListener
在视图寻呼机上使用 set 并使用该onPageSelected
方法获取当前视图,使用该viewPager.getChildAt()
方法或viewPager.getFocusedChild()
.
这是代码:
活动:
public class TimelineMomentActivity extends ActivityBase implements ViewPager.OnPageChangeListener, View.OnClickListener,
TimelineCommentsGetRequest.Callback, CreativeHandler.CreativeHandleCallback {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppInstance.sharedInstance().getBus().register(this);
mShouldSaveToDB = AppInstance.sharedInstance().isSelf();
mStory = getIntent().getParcelableExtra(StoryDB.KEY_NAME);
final String storyID = getIntent().getStringExtra(KEY_STORY_ID);
final String momentID = getIntent().getStringExtra(KEY_MOMENT_ID);
mSelectedIndex = getIntent().getIntExtra(ARG_SELECTED_INDEX, 0);
if (!mShouldSaveToDB) {
if (mStory == null) {
sendRequest(storyID, momentID);
} else {
mMoments = mStory.getMoments();
setViewPager();
}
} else {
if (mStory != null) {
mStoryDB = DBManager.getStory(mStory.getID());
} else {
mStoryDB = DBManager.getStory(storyID);
}
if (mStoryDB == null) {
sendRequest(storyID, momentID);
} else {
setGlobalDataWithStoryDB();
setViewPager();
}
}
mCreativeHandler = new CreativeHandler(this, this);
File cacheDir = Glide.getPhotoCacheDir(this, MyGlideModule.DISK_IMAGE_CACHE_NAME);
File[] filesList = cacheDir.listFiles();
for (File cachedFile : filesList) {
Log.d(TAG, "cachedFileName = " + cachedFile.getName() + " ,path = " + cachedFile.getAbsolutePath());
}
}
@Override
public Toolbar setToolbar() {
Toolbar mToolbar = (Toolbar) findViewById(R.id.mToolbar);
mToolbar.setBackgroundColor(getResources().getColor(R.color.black_color));
mToolbar.setVisibility(View.VISIBLE);
return mToolbar;
}
@Override
public void findViews() {
setContentView(R.layout.timeline_moment_activity);
mVp = (HackyViewPager) findViewById(R.id.mVp);
mTvName = (TextView) findViewById(R.id.mTvName);
mTvContent = (TextView) findViewById(R.id.mTvVpContent);
mTvDate = (TextView) findViewById(R.id.mTvUsername);
mTvNumberOfLikes = (TextView) findViewById(R.id.mTvNumberOfLikes);
mBtnLike = (ImageView) findViewById(R.id.mBtnLike);
mTvNumberOfComments = (TextView) findViewById(R.id.mTvNumberOfComments);
mBtnComments = (ImageView) findViewById(R.id.mBtnComments);
mTvNumberOfShares = (TextView) findViewById(R.id.mTvNumberOfShares);
mBtnShare = (ImageView) findViewById(R.id.mBtnShare);
mBtnLike.setOnClickListener(this);
mTvNumberOfLikes.setOnClickListener(this);
mBtnShare.setOnClickListener(this);
mTvNumberOfShares.setOnClickListener(this);
mBtnComments.setOnClickListener(this);
mTvNumberOfComments.setOnClickListener(this);
}
…..
private void setGlobalDataWithStoryDB () {
if (mStoryDB == null) {
return;
}
mMomentsDB = mStoryDB.getMoments();
mStory = mStoryDB.converter();
mMoments = mStory.getMoments();
}
// MARK: View Pager
private void setViewPager() {
mAdapter = new TimelineMomentPagerAdapter(this, mMoments, mStoryDB);
mVp.setOffscreenPageLimit(-1);
mVp.addOnPageChangeListener(this);
mVp.setAdapter(mAdapter);
mVp.setCurrentItem(mSelectedIndex);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mMoments.isEmpty()) {
return;
}
/*View currentView = mVp.getChildAt(position);
if (currentView != null) {
mAdapter.setBitmap(currentView);
} else {
currentView = mVp.getFocusedChild();
if (currentView != null) {
mAdapter.setBitmap(currentView);
}
}*/
mSelectedIndex = position;
final MomentPojo moment = mMoments.get(position);
if (getSupportActionBar() != null)
getSupportActionBar().setTitle(mStory.getTitle() + " " + (position + 1) + "/" + mMoments.size());
mTvNumberOfShares.setText(""); // TODO: No API for number of shares
handleLikeState(moment);
handleComments(moment);
mTvName.setText(moment.getOwnerName());
if (moment.getTimestamp() != null) {
mTvDate.setText(Utility.timestampToDateString(moment.getTimestamp()));
} else {
mTvDate.setVisibility(View.INVISIBLE);
}
if (moment.getTitle().equals("")) {
mTvContent.setVisibility(View.GONE);
} else {
mTvContent.setVisibility(View.VISIBLE);
mTvContent.setText(moment.getTitle());
}
}
@Override
public void onPageSelected(int position) {
View currentView = mVp.getChildAt(1);
if (currentView != null) {
mAdapter.setBitmap(currentView);
} else {
currentView = mVp.getFocusedChild();
if (currentView != null) {
mAdapter.setBitmap(currentView);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
private void handleComments(MomentPojo moment) {
final int comments = Integer.parseInt(moment.getCommentsNumber());
if (comments > 0) {
mTvNumberOfComments.setText(Utility.showNumInNumK(comments));
} else {
mTvNumberOfComments.setText("");
}
}
private void handleLikeState(MomentPojo moment) {
if (moment.wasLiked()) {
mBtnLike.setImageResource(R.drawable.ic_favorite_clicked);
} else {
mBtnLike.setImageResource(R.drawable.ic_favorite_unclicked);
}
final int likes = Integer.parseInt(moment.getLikesNumber());
if (likes > 0) {
mTvNumberOfLikes.setText(Utility.showNumInNumK(likes));
} else {
mTvNumberOfLikes.setText("");
}
}
// MARK: OnClick and OnClick actions
@Override
public void onClick(View v) {
final MomentPojo moment = mMoments.get(mSelectedIndex);
if (v == mBtnComments || v == mTvNumberOfComments) {
actionComment(mMoments.get(mSelectedIndex).getID());
} else if (v == mBtnLike || v == mTvNumberOfLikes) {
actionLike(moment);
} else if (v == mBtnShare || v == mTvNumberOfShares) {
actionShare();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent result) {
mCreativeHandler.onActivityResult(requestCode, resultCode, result);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case Crop.REQUEST_PICK:
beginCrop(result.getData());
break;
case Crop.REQUEST_CROP:
handleEdit(resultCode, result, cropFileUri);
break;
}
}
super.onActivityResult(requestCode, resultCode, result);
}
private void actionShare() {
MomentPojo momentPojo = mMoments.get(mVp.getCurrentItem());
MomentOptions.actionShare(this, momentPojo);
}
private void actionComment(String momentID) {
ProgressBarClass.startLoading(this);
new TimelineCommentsGetRequest(momentID, this);
}
private void actionLike(MomentPojo moment) {
new LinkerLikePostRequest(LinkerPojo.KEY_SOURCE_TYPE_MOMENT, moment.getID(), new LinkerLikePostRequest.Callback() {
@Override
public void onErrorResult(String err) {
// TODO: handle error
}
});
Utility.d("like state: " + moment.wasLiked());
final int likes = Integer.parseInt(moment.getLikesNumber());
if (moment.wasLiked()) {
moment.setWasLiked(false);
moment.setLikesNumber((likes - 1) + "");
mBtnLike.setImageResource(R.drawable.ic_favorite_unclicked);
} else {
moment.setWasLiked(true);
moment.setLikesNumber((likes + 1) + "");
mBtnLike.setImageResource(R.drawable.ic_favorite_clicked);
}
handleLikeState(moment);
if (mShouldSaveToDB) {
MomentDB momentDB = mMomentsDB.get(mSelectedIndex);
if (momentDB.wasLiked()) {
momentDB.setWasLiked(false);
momentDB.setLikesNumber((likes - 1) + "");
} else {
momentDB.setWasLiked(true);
momentDB.setLikesNumber((likes + 1) + "");
}
momentDB.save();
}
mMoments.set(mSelectedIndex, moment);
AppInstance.sharedInstance().getBus().post(new TimelineBusMomentChanged(moment, TimelineBusMomentChanged.KEY_STATE_LIKED));
}
@Override
public void onFinishedImageEditing(Uri outputFilePath) {
handleEdit(RESULT_OK, null, outputFilePath);
}
// MARK: Comments
@Override
public void onMomentResult(ArrayList<CommentPojo> comments) {
final LinkerPojo pojo = new LinkerPojo(mMoments.get(mSelectedIndex));
ProgressBarClass.dismissLoading();
CommentsActivity.setInstance(this, pojo, comments);
}
@Override
public void onErrorResult(String err) {
ProgressBarClass.dismissLoading();
MyToast.makeText(getString(R.string.gen_Something_went_wrong), MyToast.KEY_TYPE_RED).show();
}
// MARK: Settings
private class SettingsDialog implements ImageRotatePutRequest.Callback {
private MomentDB mMomentDB;
private ArrayList<String> mOptions;
public SettingsDialog(MomentDB momentDB) {
this.mMomentDB = momentDB;
final String type = momentDB.getType();
setOptions(type);
createDialog();
}
private void setOptions(String type) {
mOptions = new ArrayList<>();
switch (type) {
case TimelineUtils.KEY_TYPE_IMAGE:
mOptions.add(getString(R.string.rotate_left));
mOptions.add(getString(R.string.rotate_right));
//mOptions.add(getString(R.string.timeline_moment_crop));
mOptions.add(getString(R.string.timeline_moment_edit));
break;
case TimelineUtils.KEY_TYPE_TEXT:
break;
case TimelineUtils.KEY_TYPE_LINK:
break;
case TimelineUtils.KEY_TYPE_VIDEO:
break;
}
mOptions.add(getString(R.string.gen_Delete));
}
private void createDialog() {
final ListViewDialog dialog = new ListViewDialog(TimelineMomentActivity.this);
dialog.setOnItemClickListener(mOptions, new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int i, long id) {
final String option = mOptions.get(i);
if (option.equals(getString(R.string.gen_Delete))) {
actionDelete();
} else if (option.equals(getString(R.string.rotate_left))) {
actionRotate(false);
} else if (option.equals(getString(R.string.rotate_right))) {
actionRotate(true);
} /*else if (option.equals(getString(R.string.timeline_moment_crop))) {
actionCrop();
}*/ else if (option.equals(getString(R.string.timeline_moment_edit))) {
actionEdit();
}
dialog.dismiss();
}
});
dialog.show();
}
private void actionEdit() {
File bitmapFile = mAdapter.getBitmap();
if (bitmapFile != null) {
mCreativeHandler.startFeather(Uri.fromFile(bitmapFile));
}
//final MomentPojo momentPojo = mMoments.get(mVp.getCurrentItem());
//final String picUrl = Utility.getImageBySize(momentPojo.getContent(), MediaUtils.SIZE_MEDIUM, MediaUtils.SIZE_ORIGINAL);
//Uri picUri = Uri.parse(picUrl);
//mCreativeHandler.startFeather(picUri);
//File imageFile = DBManager.getImageFile(TimelineMomentActivity.this, momentPojo.toMomentDB(mStoryDB));=
}
private void actionDelete() {
MomentPojo currentMomentPojo = mMoments.get(mVp.getCurrentItem());
MomentOptions.actionDeleteMoment(TimelineMomentActivity.this, currentMomentPojo, mMoments.size(), mStory.getID());
finish();
}
private void actionRotate(boolean isClockWise) {
MomentPojo momentPojo = mMoments.get(mVp.getCurrentItem());
new ImageRotatePutRequest(momentPojo.getID(), isClockWise, this);
float currentRotation = Float.parseFloat(mMomentDB.getRotation());
if (isClockWise) {
currentRotation += 90;
} else {
currentRotation -= 90;
}
if (mShouldSaveToDB) {
mMomentDB.setRotation(currentRotation + "");
mMomentDB.save();
momentPojo = mMomentDB.converter();
}
momentPojo.setRotation(currentRotation + "");
mMoments.set(mSelectedIndex, momentPojo);
setViewPager();
AppInstance.sharedInstance().getBus().post(new TimelineBusMomentChanged(momentPojo, TimelineBusMomentChanged.KEY_STATE_ROTATE));
}
@Override
public void onImageRotateResult() {
Utility.d("image rotated ");
}
@Override
public void onErrorResult(String err) {}
}
@Override
protected void onDestroy() {
AppInstance.sharedInstance().getBus().unregister(this);
super.onDestroy();
}
….
// MARK: Crop
private void beginCrop(Uri source) {
Crop.of(source, cropFileUri).asSquare().start(this);
}
…..
}
适配器:
public class TimelineMomentPagerAdapter extends PagerAdapter {
…
public TimelineMomentPagerAdapter(Context mContext, List<MomentPojo> mArray, StoryDB aStoryDB) {
this.mContext = mContext;
this.mArray = mArray;
this.mStoryDB = aStoryDB;
}
public File getBitmap() {
convertBitmapToFile();
return mCurrentBitmapFile;
}
public void setBitmap(View aView) {
ImageView imageView = (ImageView) aView.findViewById(R.id.mIvVpContent);
if (imageView != null) {
mCurrentImageViewBitmap = getBitmap(imageView);
}
}
private void convertBitmapToFile() {
/*View currentPagerView = mVp.getChildAt(mVp.getCurrentItem());
ImageView contentView = (ImageView) currentPagerView.findViewById(R.id.mIvVpContent);
Bitmap bitmap = getBitmap(contentView);*/
final File bitmapFolder = new File(mContext.getCacheDir(), "bitmap");
if (!bitmapFolder.exists()) {
bitmapFolder.mkdir();
}
mCurrentBitmapFile = new File(bitmapFolder, "currentBitmap");
try {
if (mCurrentBitmapFile.exists()) {
mCurrentBitmapFile.delete();
}
mCurrentBitmapFile.createNewFile();
FileOutputStream stream = new FileOutputStream(mCurrentBitmapFile);
if (mCurrentImageViewBitmap != null) {
mCurrentImageViewBitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
}
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public int getCount() {
return mArray.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((RelativeLayout) object);
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View v = inflater.inflate(R.layout.timeline_moment_viewpager, container, false);
final MomentPojo momentPojo = mArray.get(position);
mIvContent = (ImageView) v.findViewById(R.id.mIvVpContent);
mTvContent = (TextView) v.findViewById(R.id.mTvVpContent);
mIvPlay = (ImageView) v.findViewById(R.id.mIvPlay);
mPbProgressBar = (ProgressBar) v.findViewById(R.id.pbProgress);
final String type = momentPojo.getType();
final String content = momentPojo.getContent();
switch (type) {
case TimelineUtils.KEY_TYPE_IMAGE: //---------------------------------------------------IMAGE
mIvPlay.setVisibility(View.GONE);
mIvContent.setVisibility(View.VISIBLE);
mTvContent.setVisibility(View.GONE);
final String contentHigherQuality = momentPojo.getContentHigherQuality();
final String newContent;
if (JavaUtils.isNotNullNotEmptyNotWhiteSpaceOnly(contentHigherQuality)) {
newContent = contentHigherQuality;
} else if (JavaUtils.isNotNullNotEmptyNotWhiteSpaceOnly(content)) {
newContent = content;
} else {
newContent = momentPojo.getLocalPath();
}
mPbProgressBar.setVisibility(View.VISIBLE);
Glide.with(BaseApplication.getInstance()).load(newContent).asBitmap().placeholder(R.drawable.ic_action_picture).into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {
if (bitmap != null) {
mIvContent.setImageBitmap(bitmap);
}
mPbProgressBar.setVisibility(View.INVISIBLE);
}
@Override
public void onLoadFailed(final Exception e, final Drawable errorDrawable) {
mPbProgressBar.setVisibility(View.INVISIBLE);
}
});
setImageRotation(momentPojo.getRotation());
if (position == 0 && !mWasCurrentImageBitmapInitialized) {
mCurrentImageViewBitmap = getBitmap(mIvContent);
mWasCurrentImageBitmapInitialized = true;
}
break;
case TimelineUtils.KEY_TYPE_TEXT: //---------------------------------------------------TEXT
case TimelineUtils.KEY_TYPE_LINK: //---------------------------------------------------LINK
….
break;
case TimelineUtils.KEY_TYPE_AUDIO: //---------------------------------------------------AUDIO
case TimelineUtils.KEY_TYPE_VIDEO: //---------------------------------------------------VIDEO
…
break;
case TimelineUtils.KEY_TYPE_PDF: //-----------------------------------------------------PDF
….
break;
case TimelineUtils.KEY_TYPE_YOUTUBE: //---------------------------------------------------VIDEO
….
break;
}
container.addView(v);
return v;
}
….
public Bitmap getBitmap(ImageView aImageView) {
Bitmap image = null;
if (aImageView == null) return null;
Drawable drawable = aImageView.getDrawable();
if (drawable != null) {
if (drawable instanceof GlideBitmapDrawable) {
GlideBitmapDrawable bitmapDrawable = (GlideBitmapDrawable) aImageView.getDrawable();
image = bitmapDrawable.getBitmap();
} else if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) aImageView.getDrawable();
image = bitmapDrawable.getBitmap();
}
}
return image;
}
….
}
此代码有效,但并非总是如此,在某些情况下 currentView 在传递此方法后为空。经过一些调试会话后,我发现虽然onPageSelected
给了我可以是例如 10 的真实索引,但视图寻呼机始终将其视图保持在 0-2 位置。因此,在刷卡时,所有三个项目都被交换,但它们仍保持在 0-2 的位置。
我怎样才能完成我的任务?