Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 仿網易新聞客戶端分類排序功能

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

編輯:關於Android編程

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

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;
  }
@Override
public 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

@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l)
{
  // ......
  ((GridViewSortAdapter) getAdapter()).hideView(i);
  // ......
}
GridViewSortAdapter
public void hideView(int item)
{
  // ......
  mStartHideItemPosition = item;
  notifyDataSetChanged();
}
private int mStartHideItemPosition = AdapterView.INVALID_POSITION;
@Override
public 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);
}
GridSortAdapter
public 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 仿網易新聞客戶端分類排序功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對本站網站的支持!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved