国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android 仿網易新聞客戶端分類排序功能

2019-12-12 04:12:45
字體:
來源:轉載
供稿:網友

先來看看網易新聞客戶端以及自己實現的效果圖,效果當然還是網易的好

gridviewsort.gif

如何實現拖拽一個Item

用WindowManager添加一個ImageView,并且將這個ImageView的顯示圖片設置成被拖拽item的截圖,截圖可以通過View的getDrawingCache獲得。拖拽的時候,隱藏原始的item。處理觸摸事件的ActionMove,調整ImageView的位置,跟隨手指移動。在ActionUp的時候removeView

GridView

 @Override  public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l)  {    // 至少有兩個item的時候,才有排序    if (getChildCount() >= 2)    {      mView = view;      // 在調用getDrawingCache必須先調用      view.setDrawingCacheEnabled(true);      // 獲取截圖并設置      Bitmap bitmap = view.getDrawingCache();      mDragItemView.setImageBitmap(bitmap);      // 設置拖拽的imageview的params      mDragItemLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;      mDragItemLayoutParams.width = bitmap.getWidth();      mDragItemLayoutParams.height = bitmap.getHeight();      mDragItemLayoutParams.x = (mDownX - mDragItemLayoutParams.width / 2);      mDragItemLayoutParams.y = (mDownY - mDragItemLayoutParams.height / 2);      // 設置拖拽imageview的中心位于長按點擊點      mDragItemLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE //不接受按鍵事件          | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE // 不接收觸摸事件          | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON  // 保持常亮          | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; // place the window within the entire screen, ignoring decorations around the border (such as the status bar)      mDragItemLayoutParams.format = PixelFormat.TRANSLUCENT;      mDragItemLayoutParams.windowAnimations = 0;      // 往WindowManager中添加拖拽的View      mWindowManager.addView(mDragItemView, mDragItemLayoutParams);      ((GridViewSortAdapter) getAdapter()).init();      ((GridViewSortAdapter) getAdapter()).hideView(i);      Log.d(TAG, "long click = " + i);      mDragStarted = true;    }    return true;  }@Overridepublic boolean onTouchEvent(MotionEvent ev){  switch (ev.getAction() & ev.getActionMasked())  {    case MotionEvent.ACTION_DOWN:      mDownX = (int) ev.getRawX();      mDownY = (int) ev.getRawY();      break;    case MotionEvent.ACTION_MOVE:      if (mDragStarted)      {        // 保持中心        mDragItemLayoutParams.x = (int) (ev.getRawX() - mDragItemView.getWidth() / 2);        mDragItemLayoutParams.y = (int) (ev.getRawY() - mDragItemView.getHeight() / 2);        // 更新params        mWindowManager.updateViewLayout(mDragItemView, mDragItemLayoutParams);        // ......      }      break;    case MotionEvent.ACTION_UP:      // ......      break;  }  return super.onTouchEvent(ev);}

如何實現隱藏拖拽的Item

在開始拖拽的時候,把隱藏的item的position告訴Adapter,調用Adapter的notifyDataSetChanged刷新數據,在getView方法中判斷當前的構建的item的position是不是需要隱藏的position是的話就設置view為inVisible

GridView

@Overridepublic boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l){  // ......  ((GridViewSortAdapter) getAdapter()).hideView(i);  // ......}GridViewSortAdapterpublic void hideView(int item){  // ......  mStartHideItemPosition = item;  notifyDataSetChanged();}private int mStartHideItemPosition = AdapterView.INVALID_POSITION;@Overridepublic View getView(int position, View convertView, ViewGroup parent){  ViewHolder holder = null;  if (convertView == null)  {    convertView = LayoutInflater.from(mContext).inflate(R.layout.view_item_grid_view_sort, null);    holder = new ViewHolder();    holder.title = (TextView) convertView.findViewById(R.id.view_item_grid_view_sort_title);    convertView.setTag(holder);  }  else  {    holder = (ViewHolder) convertView.getTag();  }  holder.title.setText(mTypeTitle.get(position));  if (mStartHideItemPosition == position)  {    convertView.setVisibility(View.INVISIBLE);  }  else  {    convertView.setVisibility(View.VISIBLE);  }  return convertView;}

如何知道當前拖拽到哪一個item之上

要想在拖拽到其他item上面時互換位置,那必須得知道當前拖拽到了哪一個item之上。GrideView提供了一個方法叫pointToPosition,可以在處理觸摸事件的ACTION_MOVE時,獲取手指觸摸的x,y來得到當前拖拽到item之上的position。這里需要注意的一點是,在拖拽的過程,同一個item的position是不會變的,除非調用了Adapter的notifyDataSetChanged,position才會重新計算。比如position為2的item,在拖拽的過程無論怎么動畫移動位置,他的position都是2,知道一次拖拽結束,ActionUp的時候,會調用notifyDataSetChanged

GridView

@Override public boolean onTouchEvent(MotionEvent ev) {  case MotionEvent.ACTION_MOVE:  if (mDragStarted)  {    // ......    int position = pointToPosition((int) ev.getX(), (int) ev.getY());    // ......  }  break;}

如何實現動畫

一個item需要水平以及垂直需要移動的距離可以事先先計算出來,其實水平距離不管怎么樣一定會是GridView一個單元格的寬度加上水平間距,垂直距離無論如何都是一個單元格的高度加上垂直距離,寬度非常好取,高度的話,這里默認item 的高度和單元格的高度相同。

GridViewSortAdapter

View view = mGridView.getChildAt(0);mTranslateX = view.getWidth() + mHorizontalSpace;mTranslateY = view.getHeight() + mVerticalSpace;

當拖拽到其他item之上時,開始動畫

SortGridView

if (position != AdapterView.INVALID_POSITION && !((GridViewSortAdapter) getAdapter()).isInAnimation()){     Log.d(TAG, "position = " + position);     ((GridViewSortAdapter) getAdapter()).swap(position);}GridSortAdapterpublic void swap(int position){  mAnimatorSetList.clear();  int r_p = mPositionList.indexOf(position);  Log.d(TAG, "r_p = " + r_p);  if (mCurrentHideItemPosition < r_p)  {    for (int i = mCurrentHideItemPosition + 1; i <= r_p; i++)    {      View v = mGridView.getChildAt(mPositionList.get(i));      if (i % mColsNum == 0 && i > 0)      {        startMoveAnimation(v, v.getTranslationX() + mTranslateX * (mColsNum - 1), v.getTranslationY() -            mTranslateY);      }      else      {        startMoveAnimation(v, v.getTranslationX() - mTranslateX, 0);      }    }  }  else if (mCurrentHideItemPosition > r_p)  {    for (int i = r_p; i < mCurrentHideItemPosition; i++)    {      View v = mGridView.getChildAt(mPositionList.get(i));      if ((i + 1) % mColsNum == 0)      {        startMoveAnimation(v, v.getTranslationX() - mTranslateX * (mColsNum - 1), v.getTranslationY() + mTranslateY);      }      else      {        startMoveAnimation(v, v.getTranslationX() + mTranslateX, 0);      }    }  }  resetPositionList();  int value = mPositionList.get(mStartHideItemPosition);  if (mStartHideItemPosition < r_p)  {    mPositionList.add(r_p + 1, value);    mPositionList.remove(mStartHideItemPosition);  }  else if (mStartHideItemPosition > r_p)  {    mPositionList.add(r_p, value);    mPositionList.remove(mStartHideItemPosition + 1);  }  mCurrentHideItemPosition = r_p;}public boolean isInAnimation(){  return mInAnimation;}private void resetPositionList(){  mPositionList.clear();  for (int i = 0; i < mGridView.getChildCount(); i++)  {    mPositionList.add(i);  }}private void startMoveAnimation(View myView, float x, float y){  AnimatorSet set = new AnimatorSet();  set.playTogether(      ObjectAnimator.ofFloat(myView, "translationX", myView.getTranslationX(), x),      ObjectAnimator.ofFloat(myView, "translationY", myView.getTranslationY(), y)  );  set.addListener(new Animator.AnimatorListener()  {    @Override    public void onAnimationStart(Animator animator)    {      mInAnimation = true;    }    @Override    public void onAnimationEnd(Animator animator)    {      mInAnimation = false;    }    @Override    public void onAnimationCancel(Animator animator)    {    }    @Override    public void onAnimationRepeat(Animator animator)    {    }  });  mAnimatorSetList.add(set);  set.setDuration(150).start();}

這里我主要解釋一下代碼中 mPositionList這個列表的作用,之前說過一次拖拽的時候,item的position是不會變化的。

假設有一組數據

a b c d
e f g h
i j k l

此時mPositionList的內容就是 0 1 2 3 4 5 6 7 8 9 10 11 12

現在將c拖拽到g上,拖拽完成之后的數據應該是,未釋放手指

a b d e
f g c h
i j k l

此時mPositionList的內容就是 0 1 2 4 5 6 7 3 8 9 10 11 12

緊接著,繼續拖拽c到e上,你會發現調用pointToPosition方法得到的position是5,但是e現在的索引是4

因此你只需要調用

mPositionList.indexOf(pointToPosition(x,y))

就能得到真實的item的position

其他

如果把GridView的列數變成1那么似曾相識啊

gridviewex.gif

源碼地址

https://github.com/jiahuanyu/android-example-code/tree/master/app/src/main/java/com/github/jiahuanyu/example/ui/dragsortgird

以上所述是小編給大家介紹的Android 仿網易新聞客戶端分類排序功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 汉沽区| 鄢陵县| 商水县| 堆龙德庆县| 兴业县| 海兴县| 于都县| 桂阳县| 镇平县| 莱州市| 临安市| 绥芬河市| 贵定县| 砚山县| 宜黄县| 兴山县| 阿城市| 壤塘县| 将乐县| 介休市| 丰城市| 西平县| 青神县| 墨脱县| 久治县| 长治市| 桐城市| 石景山区| 萝北县| 榆林市| 九江县| 苏尼特左旗| 临武县| 岢岚县| 金沙县| 庆城县| 临安市| 托克托县| 江北区| 柳江县| 威远县|