更改Listview行的背景

时间:2016-10-28 20:17:33

标签: java android listview

我读过文章"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;
    }

}

1 个答案:

答案 0 :(得分:0)

您需要做的就是告诉ListView为所选项目使用不同的背景:

https://developer.android.com/reference/android/widget/AbsListView.html#attr_android:listSelector