<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android仿微信圖片詳情頁面,可下拉關(guān)閉頁面

          共 18760字,需瀏覽 38分鐘

           ·

          2021-07-17 07:01

          效果圖:



          1、要實現(xiàn)效果圖的方案,需要操作重寫ViewPager的事件處理。


          2、下滑?透明的方案可以使用設(shè)置背景來實現(xiàn)

          ?

          下拉縮放的效果需要重寫onInterceptTouchEvent和onTouchEvent,?在onInterceptTouchEvent中不攔截down事件,并且在move事件中判斷是否滿足下滑縮放的條件;


          在onTouchEvent中實現(xiàn)具體的縮放以及透明度變化的效果;


          同時在ViewPager的滑動要與下滑縮放區(qū)分開,因此需要監(jiān)聽OnPageChangeListener,并在onTouchEvent判斷是否ViewPager在滑動中

          public class DragViewPager extends ViewPager implements View.OnClickListener {    public static final int STATUS_NORMAL = 0;//正常瀏覽狀態(tài)    public static final int STATUS_MOVING = 1;//滑動狀態(tài)    public static final int STATUS_RESETTING = 2;//返回中狀態(tài)    public static final String TAG = "DragViewPager";

          public static final float MIN_SCALE_SIZE = 0.3f;//最小縮放比例 public static final int BACK_DURATION = 300;//ms public static final int DRAG_GAP_PX = 50;
          private int currentStatus = STATUS_NORMAL; private int currentPageStatus;
          private float mDownX; private float mDownY; private float screenHeight;
          /** * 要縮放的View */ private View currentShowView; /** * 滑動速度檢測類 */ private VelocityTracker mVelocityTracker; private IAnimClose iAnimClose;
          public void setIAnimClose(IAnimClose iAnimClose) { this.iAnimClose = iAnimClose; }
          public DragViewPager(Context context) { super(context); init(context); }
          public DragViewPager(Context context, AttributeSet attrs) { super(context, attrs); init(context); }
          public void init(Context context) { screenHeight = ScreenUtils.getScreenHeight(context); setBackgroundColor(Color.BLACK); addOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
          @Override public void onPageSelected(int position) {
          }
          @Override public void onPageScrollStateChanged(int state) { currentPageStatus = state; } }); }
          public void setCurrentShowView(View currentShowView) { this.currentShowView = currentShowView; if (this.currentShowView != null) { this.currentShowView.setOnClickListener(this); }    }
          //配合SubsamplingScaleImageView使用,根據(jù)需要攔截ACTION_MOVE @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (getAdapter() instanceof ImagePagerAdapter) { ImagePagerAdapter adapter = ((ImagePagerAdapter) getAdapter()); SubsamplingScaleImageView mImage = (SubsamplingScaleImageView) adapter.getItem(getCurrentItem()).getView().findViewById(R.id.image); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.e("jc","onInterceptTouchEvent:ACTION_DOWN"); mDownX = ev.getRawX(); mDownY = ev.getRawY(); break; case MotionEvent.ACTION_MOVE: Log.e("jc","onInterceptTouchEvent:ACTION_MOVE"); if (mImage.getCenter() != null && mImage.getCenter().y <= mImage.getHeight() / mImage.getScale() / 2) { Log.e("jc","onInterceptTouchEvent:ACTION_MOVE"); int deltaX = Math.abs((int) (ev.getRawX() - mDownX)); int deltaY = (int) (ev.getRawY() - mDownY); if (deltaY > DRAG_GAP_PX && deltaX <= DRAG_GAP_PX) {//往下移動超過臨界,左右移動不超過臨界時,攔截滑動事件 return true; } } break; case MotionEvent.ACTION_UP: Log.e("jc","onInterceptTouchEvent:ACTION_UP"); break; } } return super.onInterceptTouchEvent(ev); }
          @Override public boolean onTouchEvent(MotionEvent ev) { if (currentStatus == STATUS_RESETTING) return false; switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: mDownX = ev.getRawX(); mDownY = ev.getRawY(); addIntoVelocity(ev); break; case MotionEvent.ACTION_MOVE: addIntoVelocity(ev); int deltaY = (int) (ev.getRawY() - mDownY); //手指往上滑動 if (deltaY <= DRAG_GAP_PX && currentStatus != STATUS_MOVING) return super.onTouchEvent(ev); //viewpager不在切換中,并且手指往下滑動,開始縮放 if (currentPageStatus != SCROLL_STATE_DRAGGING && (deltaY > DRAG_GAP_PX || currentStatus == STATUS_MOVING)) { moveView(ev.getRawX(), ev.getRawY()); return true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (currentStatus != STATUS_MOVING) return super.onTouchEvent(ev); final float mUpX = ev.getRawX(); final float mUpY = ev.getRawY();
          float vY = computeYVelocity();//松開時必須釋放VelocityTracker資源 if (vY >= 1200 || Math.abs(mUpY - mDownY) > screenHeight / 4) { //下滑速度快,或者下滑距離超過屏幕高度的一半,就關(guān)閉 if (iAnimClose != null) { iAnimClose.onPictureRelease(currentShowView); } } else { resetReviewState(mUpX, mUpY); } break; }
          return super.onTouchEvent(ev); }
          //返回瀏覽狀態(tài) private void resetReviewState(final float mUpX, final float mUpY) { currentStatus = STATUS_RESETTING; if (mUpY != mDownY) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(mUpY, mDownY); valueAnimator.setDuration(BACK_DURATION); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float mY = (float) animation.getAnimatedValue(); float percent = (mY - mDownY) / (mUpY - mDownY); float mX = percent * (mUpX - mDownX) + mDownX; moveView(mX, mY); if (mY == mDownY) { mDownY = 0; mDownX = 0; currentStatus = STATUS_NORMAL; } } }); valueAnimator.start(); } else if (mUpX != mDownX) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(mUpX, mDownX); valueAnimator.setDuration(BACK_DURATION); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float mX = (float) animation.getAnimatedValue(); float percent = (mX - mDownX) / (mUpX - mDownX); float mY = percent * (mUpY - mDownY) + mDownY; moveView(mX, mY); if (mX == mDownX) { mDownY = 0; mDownX = 0; currentStatus = STATUS_NORMAL; } } }); valueAnimator.start(); } else if (iAnimClose != null) iAnimClose.onPictureClick(); } //移動View private void moveView(float movingX, float movingY) { if (currentShowView == null) return; currentStatus = STATUS_MOVING; float deltaX = movingX - mDownX; float deltaY = movingY - mDownY; float scale = 1f; float alphaPercent = 1f; if (deltaY > 0) { scale = 1 - Math.abs(deltaY) / screenHeight; alphaPercent = 1 - Math.abs(deltaY) / (screenHeight / 2); }
          ViewHelper.setTranslationX(currentShowView, deltaX); ViewHelper.setTranslationY(currentShowView, deltaY); scaleView(scale); setBackgroundColor(getBlackAlpha(alphaPercent)); }
          //縮放View private void scaleView(float scale) { scale = Math.min(Math.max(scale, MIN_SCALE_SIZE), 1); ViewHelper.setScaleX(currentShowView, scale); ViewHelper.setScaleY(currentShowView, scale);    }
          private int getBlackAlpha(float percent) { percent = Math.min(1, Math.max(0, percent)); int intAlpha = (int) (percent * 255); return Color.argb(intAlpha,0,0,0); }
          private void addIntoVelocity(MotionEvent event) { if (mVelocityTracker == null) mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker.addMovement(event); }
          private float computeYVelocity() { float result = 0; if (mVelocityTracker != null) { mVelocityTracker.computeCurrentVelocity(1000); result = mVelocityTracker.getYVelocity(); releaseVelocity(); } return result; }
          private void releaseVelocity() { if (mVelocityTracker != null) { mVelocityTracker.clear(); mVelocityTracker.recycle(); mVelocityTracker = null; } }
          @Override public void onClick(View v) { if (iAnimClose != null) { iAnimClose.onPictureClick(); } }
          public interface IAnimClose { void onPictureClick();
          void onPictureRelease(View view);    }}


          需要進行縮放的View我這里在Adapter中添加回調(diào)設(shè)置,并且adapter可以實現(xiàn)更新的效果

          public class ImagePagerAdapter extends FragmentStatePagerAdapter {    private DragViewPager mPager;    private ArrayList<Fragment> mFragmentList;
          public ImagePagerAdapter(FragmentManager fm, List<String> datas,DragViewPager pager) { super(fm); mPager=pager; mPager.setAdapter(this); updateData(datas); }
          public void updateData(List<String> dataList) { ArrayList<Fragment> fragments = new ArrayList<>(); for (int i = 0, size = dataList.size(); i < size; i++) { final ImageDetailFragment fragment = ImageDetailFragment.newInstance(dataList.get(i)); fragment.setOnImageListener(new ImageDetailFragment.OnImageListener() { @Override public void onInit() { View view = fragment.getView(); mPager.setCurrentShowView(view); } }); fragments.add(fragment); } setViewList(fragments); }
          private void setViewList(ArrayList<Fragment> fragmentList) { if (mFragmentList != null) { mFragmentList.clear(); } mFragmentList = fragmentList; notifyDataSetChanged(); }
          @Override public int getCount() { return mFragmentList==null?0:mFragmentList.size(); }
          public int getItemPosition(Object object) { return POSITION_NONE; }
          @Override public Fragment getItem(int position) { return mFragmentList.get(position);    }}


          要實現(xiàn)透明度變化的效果還需要對activity設(shè)置theme

          <style name="translucent" parent="AppTheme">        <item name="windowActionBar">false</item>        <item name="windowNoTitle">true</item>        <item name="android:windowIsTranslucent">true</item>        <item name="android:windowBackground">@android:color/transparent</item></style>
          <activity android:name=".ui.ImagePagerActivity"            android:theme="@style/translucent"/>


          在需要使用的頁面只需要調(diào)用即可

          ImagePagerActivity.startImagePage(MainActivity.this,                        urls,pos,recyclerView.getLayoutManager().findViewByPosition(pos));


          在整個demo中采用的轉(zhuǎn)場動畫,需要設(shè)置共享元素,因此在需要使用的頁面需要設(shè)置如下:


          首先設(shè)置轉(zhuǎn)場動畫的共享元素,因為跳轉(zhuǎn)和返回時都會調(diào)用onMapSharedElements,需要判斷bundle是否為空,bundle會在返回的時候在onActivityReenter獲取到

          //設(shè)置轉(zhuǎn)場動畫的共享元素,因為跳轉(zhuǎn)和返回時都會調(diào)用onMapSharedElements,需要判斷bundle是否為空        setExitSharedElementCallback(new SharedElementCallback() {            @Override            public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {                if (bundle!=null){                    int index = bundle.getInt(ImagePagerActivity.STATE_POSITION,0);                    sharedElements.clear();                    sharedElements.put("img", recyclerView.getLayoutManager().findViewByPosition(index));                    bundle=null;                }            }        });


          其次在返回的時候獲取數(shù)據(jù)bundle

          @Override    public void onActivityReenter(int resultCode, Intent data) {        super.onActivityReenter(resultCode, data);        bundle = data.getExtras();        int currentPosition = bundle.getInt(ImagePagerActivity.STATE_POSITION,0);        //做相應(yīng)的滾動        recyclerView.scrollToPosition(currentPosition);        //暫時延遲 Transition 的使用,直到我們確定了共享元素的確切大小和位置才使用        //postponeEnterTransition后不要忘記調(diào)用startPostponedEnterTransition        ActivityCompat.postponeEnterTransition(this);        recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {            @Override            public boolean onPreDraw() {                recyclerView.getViewTreeObserver().removeOnPreDrawListener(this);                // TODO: figure out why it is necessary to request layout here in order to get a smooth transition.                recyclerView.requestLayout();                //共享元素準備好后調(diào)用startPostponedEnterTransition來恢復(fù)過渡效果                ActivityCompat.startPostponedEnterTransition(MainActivity.this);                return true;            }        });    }


          完整的調(diào)用頁面的代碼如下:

          public class MainActivity extends AppCompatActivity {
          private RecyclerView recyclerView;
          private MainAdapter mainAdapter;
          //圖片集合 private ArrayList<String> urls;
          //存放返回時當前頁碼 private Bundle bundle;
          @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); urls=new ArrayList<>(); //為了顯示效果,重復(fù)添加了三次 urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524477979306&di=3eb07e9302606048abe13d7b6a2bc601&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201406%2F12%2F20140612211118_YYXAC.jpeg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463580&di=1315bc4db30999f00b89ef79c3bb06e5&imgtype=0&src=http%3A%2F%2Fpic36.photophoto.cn%2F20150710%2F0005018721870517_b.jpg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463575&di=6221f21bcb761675c5d161ebc53d5948&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201410%2F03%2F20141003112442_AkkuH.thumb.700_0.jpeg");
          urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524477979306&di=3eb07e9302606048abe13d7b6a2bc601&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201406%2F12%2F20140612211118_YYXAC.jpeg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463580&di=1315bc4db30999f00b89ef79c3bb06e5&imgtype=0&src=http%3A%2F%2Fpic36.photophoto.cn%2F20150710%2F0005018721870517_b.jpg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463575&di=6221f21bcb761675c5d161ebc53d5948&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201410%2F03%2F20141003112442_AkkuH.thumb.700_0.jpeg");
          urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524477979306&di=3eb07e9302606048abe13d7b6a2bc601&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201406%2F12%2F20140612211118_YYXAC.jpeg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463580&di=1315bc4db30999f00b89ef79c3bb06e5&imgtype=0&src=http%3A%2F%2Fpic36.photophoto.cn%2F20150710%2F0005018721870517_b.jpg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463575&di=6221f21bcb761675c5d161ebc53d5948&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201410%2F03%2F20141003112442_AkkuH.thumb.700_0.jpeg"); initView(); }
          private void initView() { recyclerView = (RecyclerView) findViewById(R.id.recycler); recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); mainAdapter = new MainAdapter(urls); mainAdapter.setOnItemClickListener(new MainAdapter.OnItemClickListener() { @Override public void onItemClick(int pos) { ImagePagerActivity.startImagePage(MainActivity.this, urls,pos,recyclerView.getLayoutManager().findViewByPosition(pos)); } }); recyclerView.setAdapter(mainAdapter);
          //設(shè)置轉(zhuǎn)場動畫的共享元素,因為跳轉(zhuǎn)和返回都會調(diào)用,需要判斷bundle是否為空 setExitSharedElementCallback(new SharedElementCallback() { @Override public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) { if (bundle!=null){ int index = bundle.getInt(ImagePagerActivity.STATE_POSITION,0); sharedElements.clear(); sharedElements.put("img", recyclerView.getLayoutManager().findViewByPosition(index)); bundle=null; } } }); }
          //返回的時候獲取數(shù)據(jù) @Override public void onActivityReenter(int resultCode, Intent data) { super.onActivityReenter(resultCode, data); bundle = data.getExtras(); int currentPosition = bundle.getInt(ImagePagerActivity.STATE_POSITION,0); //做相應(yīng)的滾動 recyclerView.scrollToPosition(currentPosition); //暫時延遲 Transition 的使用,直到我們確定了共享元素的確切大小和位置才使用 //postponeEnterTransition后不要忘記調(diào)用startPostponedEnterTransition ActivityCompat.postponeEnterTransition(this); recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { recyclerView.getViewTreeObserver().removeOnPreDrawListener(this); // TODO: figure out why it is necessary to request layout here in order to get a smooth transition. recyclerView.requestLayout(); //共享元素準備好后調(diào)用startPostponedEnterTransition來恢復(fù)過渡效果 ActivityCompat.startPostponedEnterTransition(MainActivity.this); return true; } }); }}


          源碼地址:

          https://github.com/JohnsonHou/ImageReview


          到這里就結(jié)束啦。

          瀏覽 37
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  麻豆精品秘 国产视频 | 高清一区在线观看视频 | 婷婷视频| 一区二 三区免费 | 久久精品成人电影 |