Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applauze like listview

I am trying to make a custom Listview like in the ios app Applauze.

I extended the listview class and with the help of onTouchEvent tried to detect the movement of the child rows and change their heights on movement. So that the topmost child has the largest height as compared to other rows.

  public class CustView extends ListView{

    private float mLastTouchY;
    private int mActivePointerId;
    private boolean up=false;
    private boolean down=false;
    private final Camera mCamera = new Camera();
    private final Matrix mMatrix = new Matrix();
    private Context context;
    private Paint mPaint;


    public CustView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        this.setChildrenDrawingOrderEnabled(true);
    }   
    public CustView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }

    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        // get top left coordinates
        boolean isTop = false;
        final int top = child.getTop();
        final int bottom = child.getBottom();
        child.setMinimumHeight(getHeight()/3);
        Bitmap bitmap = child.getDrawingCache();
        Bitmap cropBitmap;
        if (bitmap == null) {
            child.setDrawingCacheEnabled(true);
            child.buildDrawingCache();
            bitmap = child.getDrawingCache();
        }
        int belowE = (child.getHeight()*2/3)+getPaddingTop();
        int aboveE = (child.getHeight())+getPaddingTop();
        mCamera.save();
        if(up){
            if (top>=belowE) {
                //make all small
                isTop = true;
                //canvas.scale(1.0f, 0.5f);
                cropBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight()/2);
                child.setMinimumHeight(2);
                //child.setLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
                child.setPressed(true);
                Log.e("Chota", child.getMeasuredHeight()+"True"+top);
            }  
            else {
                //canvas.scale(1.0f,xy);
                cropBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight());
                //child.setLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
                //child.setMinimumHeight(4);
                Log.e("Bada", child.getMeasuredHeight()+"False"+top);
                child.setPressed(false);
            };
        }
        else{
            if (bottom>aboveE) {
                //make center row bigger
                isTop = true;
                //canvas.scale(1.0f, 0.5f);
                cropBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight()/2);
                child.setMinimumHeight(2);
                child.setPressed(true);
                Log.e("Bada", child.getMeasuredHeight()+"True"+top);
            }  
            else {
                //canvas.scale(1.0f,xy);
                cropBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight());
                //child.setMinimumHeight(getHeight()/4);
                Log.e("Chota", child.getMeasuredHeight()+"False"+top);
                child.setPressed(false);
            };
        }

            mCamera.getMatrix(mMatrix);
        mCamera.restore();

        // create and initialize the paint object
        if (mPaint == null) {
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setFilterBitmap(true);
        }
        mMatrix.postScale(1.0f, 1.5f);
        mMatrix.postTranslate(child.getLeft(), top);
        canvas.drawBitmap(cropBitmap, mMatrix, mPaint);
        //Log.e("Up", "Child"+top+" "+getTop());
        return false;
    }



    /* (non-Javadoc)
     * @see android.widget.AbsListView#onTouchEvent(android.view.MotionEvent)
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        final int action = MotionEventCompat.getActionMasked(ev); 

        int INVALID_POINTER_ID=65421385;
        switch (action) { 
        case MotionEvent.ACTION_DOWN: {
            final int pointerIndex = MotionEventCompat.getActionIndex(ev); 
            // Remember where we started (for dragging)
            mLastTouchY = MotionEventCompat.getY(ev, pointerIndex);
            // Save the ID of this pointer (for dragging)
            mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
            Log.e("Down", "Down");
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            // Find the index of the active pointer and fetch its position
            final int pointerIndex = 
                    MotionEventCompat.findPointerIndex(ev, mActivePointerId);  
            final float y = MotionEventCompat.getY(ev, pointerIndex);

            // Calculate the distance moved
            final float dy = y - mLastTouchY;

            up = dy<0;
            down = dy>0;

            //((MyAdapter)getListAdapter()).animate(fVI,top,bottom,getChildCount());
            if(Math.abs(dy)>10){
                Log.e("Dist", "D-"+Math.abs(dy));
                invalidate();
            }

            // Remember this touch position for the next move event
            mLastTouchY = y;
            Log.e("Move", "Move");
            break;
        }

        case MotionEvent.ACTION_UP: {
            mActivePointerId = INVALID_POINTER_ID;
            Log.e("Up", "Up");
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {

            final int pointerIndex = MotionEventCompat.getActionIndex(ev); 
            final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); 

            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex); 
                mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
            }
            break;
        }
        }
        return super.onTouchEvent(ev);
    }

    /* (non-Javadoc)
     * @see android.view.View#onScrollChanged(int, int, int, int)
     */
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        // TODO Auto-generated method stub
        super.onScrollChanged(l, t, oldl, oldt);
    }
}

But the problem is that the drawchild function is being called repeatedly as i saw in my logs which is making the listview less responsive. And also what would be the best way to apply animation to each row?? If anyone knows the reason please let me know!!! Thanks.

like image 253
user2405247 Avatar asked Nov 12 '22 05:11

user2405247


1 Answers

As you are doing lot of work in drawChild() function which is called repeatedly will obviously insert lagging thereby making your listview less responsive. So, possibly you can skip some of the drawChild() function calls based on some timer or other logic. This we normally do when we handle sensor events in the application. Implementing this should be simple only.

For list view row animations you can follow the below link. Best way to animate will be to write animation xmls and then use them to animate rows in listview:

http://karnshah8890.blogspot.kr/2013/04/listview-animation-tutorial.html

Hope this helps.

like image 70
Sushil Avatar answered Nov 15 '22 11:11

Sushil