2016-10-28 140 views
0

我看過文章"Listview slide to remove",現在想實現"Listview to Highlight"想想,所以基本上我想改變所選行的背景顏色。問題是當我突出顯示一行時,它會自動突出顯示另一個不可見的行。 (我需要向下滾動才能看到它)更改列表視圖行的背景

這裏是我的代碼(其實不是我的):

MainActivity:

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_list_view_deletion); 

     mListView = (ListView) findViewById(R.id.listview); 
     mainView = (LinearLayout) findViewById(R.id.listViewBackground1); 
     final ArrayList<String> cheeseList = new ArrayList<String>(); 
     for (int i = 0; i < Cheeses.sCheeseStrings.length; ++i) { 
      cheeseList.add(Cheeses.sCheeseStrings[i]); 
     } 
     mAdapter = new StableArrayAdapter(this,R.layout.opaque_text_view, cheeseList, mTouchListener); 
     mListView.setAdapter(mAdapter); 
    } 

    private View.OnTouchListener mTouchListener = new View.OnTouchListener() { 

     float mDownX; 
     private int mSwipeSlop = -1; 

     @Override 
     public boolean onTouch(final View v, MotionEvent event) { 
      if (mSwipeSlop < 0) { 
       mSwipeSlop = ViewConfiguration.get(ListViewRemovalAnimation.this). 
         getScaledTouchSlop(); 
      } 
      switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       if (mItemPressed) { 
        return false; 
       } 
       mItemPressed = true; 
       mDownX = event.getX(); 
       break; 
      case MotionEvent.ACTION_CANCEL: 
       v.setTranslationX(0); 
       mItemPressed = false; 
       break; 
      case MotionEvent.ACTION_MOVE: 
       { 
        float x = event.getX() + v.getTranslationX(); 
        float deltaX = x - mDownX; 
        float deltaXAbs = Math.abs(deltaX); 
        if(deltaX > 0.0) { 
         mainView.setBackgroundColor(Color.GREEN); 
        } 
        else { 
         mainView.setBackgroundColor(Color.RED); 
        } 
        if (!mSwiping) { 
         if (deltaXAbs > mSwipeSlop) { 
          mSwiping = true; 
          mListView.requestDisallowInterceptTouchEvent(true); 
         } 
        } 
        if (mSwiping) { 
         v.setTranslationX((x - mDownX)); 
        } 
       } 
       break; 
      case MotionEvent.ACTION_UP: 
       {if (mSwiping) { 
         float x = event.getX() + v.getTranslationX(); 
         float deltaX = x - mDownX; 
         float deltaXAbs = Math.abs(deltaX); 
         float fractionCovered; 
         float endX; 
         final boolean remove; 
         final boolean removeOr; 
         if (deltaXAbs > v.getWidth()/4) { 
          // Greater than a quarter of the width - animate it out 
          fractionCovered = deltaXAbs/v.getWidth(); 
          endX = deltaX < 0 ? -v.getWidth() : v.getWidth(); 
          remove = true; 
         } else { 
          // Not far enough - animate it back 
          fractionCovered = 1 - (deltaXAbs/v.getWidth()); 
          endX = 0; 
          remove = false; 
         } 

         removeOr = (deltaX > 0 ? true : false); 

         long duration = (int) ((1 - fractionCovered) * SWIPE_DURATION); 
         mListView.setEnabled(false); 
         v.animate().setDuration(duration).translationX(endX). 
           withEndAction(new Runnable() { 
            @Override 
            public void run() { 

             v.setTranslationX(0); 
             if (remove) { 
              //int position = mListView.getPositionForView(v); 
              //mAdapter.remove(mAdapter.getItem(position)); 
              animateRemoval(mListView, v, removeOr); 
             } else { 
              mSwiping = false; 
              mListView.setEnabled(true); 
             } 
            } 
           }); 
        } 
       } 
       mItemPressed = false; 
       break; 
      default: 
       return false; 
      } 
      return true; 
     } 
    }; 

    private void animateRemoval(final ListView listview, View viewToRemove, boolean removeOr) { 

     int firstVisiblePosition = listview.getFirstVisiblePosition(); //first visible position in listview 
     for (int i = 0; i < listview.getChildCount(); ++i) { // iterate 11 visible elements 
      View child = listview.getChildAt(i); // current visible element 
      if (child != viewToRemove) { // if the current item is not the one we need to remove 
       int position = firstVisiblePosition + i; // relative index 
       long itemId = mAdapter.getItemId(position); // global index (constant) 
       mItemIdTopMap.put(itemId, child.getTop()); // putto the map 
      } 
     } 

     int position = mListView.getPositionForView(viewToRemove); // position to remove from listview (relative) 
     if(removeOr == false) mAdapter.remove(mAdapter.getItem(position)); 
     else { 
      //Log.w("----", "sample"); 
      viewToRemove.setBackgroundColor(Color.GREEN); 
     } 
     // 
     // 
     // 
     //SAVE TO THE MAP AND REMOVE FROM ADAPTER 
     // 
     // 
     // 


     final ViewTreeObserver observer = listview.getViewTreeObserver(); 

     observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
      public boolean onPreDraw() { 
       observer.removeOnPreDrawListener(this); // remove previous callback 
       boolean firstAnimation = true; // flag for animation algo 
       int firstVisiblePosition = listview.getFirstVisiblePosition(); //first visible view index 
       for (int i = 0; i < listview.getChildCount(); ++i) { //iterate 11 visible elements 
        final View child = listview.getChildAt(i); // current view (by child) 
        int position = firstVisiblePosition + i; // relative index of item 

        long itemId = mAdapter.getItemId(position); // global index of item (constant) 

        Integer startTop = mItemIdTopMap.get(itemId); // top position of global item 
        int top = child.getTop(); // top position of current item 

        /* 
         If we deleted the element from visible listview area, then we have new element 
         from non-visible listview area. That is the situation when starTop == null (if 
         top position of global item "itemId" was in unvisible area before deletion.) 
        */ 
        if (startTop != null) { // item was in visible area before the deletion 
         if (startTop != top) { // if startop != top (when the deleted element was after the current) 
          int delta = startTop - top; // initial top 
          child.setTranslationY(delta); // set init top 
          child.animate().setDuration(MOVE_DURATION).translationY(0); // animate to 0 

          if (firstAnimation) { // if it is the first animation 
           child.animate().withEndAction(new Runnable() { // call end action 
            public void run() { 
             mSwiping = false; // so we can swipe again 
             mListView.setEnabled(true); // enable listview touch events 
            } 
           }); 
           firstAnimation = false; // 
          } 
         } 
        } 
        else { 

         int childHeight = child.getHeight() + listview.getDividerHeight(); // height of listview child view 
         startTop = top + childHeight; // new top for currently unvisible element 
         int delta = startTop - top; // initial top 

         child.setTranslationY(delta); // set init top 
         child.animate().setDuration(MOVE_DURATION).translationY(0); // animate to top 0 
         /* 
          if it is the first animation. It happens whwn we removed last visible element from listview. 
          So we didn't use firstAnimation flag. 
         */ 
         if (firstAnimation) { // if it is the first animation 
          child.animate().withEndAction(new Runnable() { // call end action 
           public void run() { 
            mSwiping = false; // so we can swipe again 
            mListView.setEnabled(true); // enable listview touch events 
           } 
          }); 
          firstAnimation = false; // 
         } 
        } 
       } 
       mItemIdTopMap.clear(); // free memory 
       return true; 
      } 
     }); 
    } 

StableArrayAdapter:

public class StableArrayAdapter extends ArrayAdapter<String> { 

    HashMap<String, Integer> mIdMap = new HashMap<String, Integer>(); 
    View.OnTouchListener mTouchListener; 

    public StableArrayAdapter(Context context, int textViewResourceId, 
      List<String> objects, View.OnTouchListener listener) { 
     super(context, textViewResourceId, objects); 
     mTouchListener = listener; 
     for (int i = 0; i < objects.size(); ++i) { 
      mIdMap.put(objects.get(i), i); 
     } 
    } 

    @Override 
    public long getItemId(int position) { 
     String item = getItem(position); 
     return mIdMap.get(item); 
    } 

    @Override 
    public boolean hasStableIds() { 
     return true; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View view = super.getView(position, convertView, parent); 
     view.setOnTouchListener(mTouchListener); 
     return view; 
    } 

} 

回答