5

iOSアプリApplauzeのようなカスタムListviewを作ろうとしています.

リストビュー クラスを拡張し、onTouchEvent の助けを借りて、子行の動きを検出し、動きに合わせて高さを変更しようとしました。一番上の子が他の行と比較して最大の高さを持つようにします。

  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);
    }
}

しかし問題は、ログで見たように drawchild 関数が繰り返し呼び出されているため、リストビューの応答性が低下していることです。また、各行にアニメーションを適用する最良の方法は何ですか?? 理由がわかる方教えてください!!!ありがとう。

4

1 に答える 1

1

繰り返し呼び出されるdrawChild()関数で多くの作業を行っているため、明らかに遅延が挿入され、リストビューの応答性が低下します。そのため、タイマーまたはその他のロジックに基づいて、 drawChild()関数呼び出しの一部をスキップできる可能性があります。これは通常、アプリケーションでセンサー イベントを処理するときに行います。これを実装するのは簡単です。

リスト ビューの行のアニメーションについては、以下のリンクをたどることができます。アニメーション化する最良の方法は、アニメーション xml を記述し、それらを使用してリストビューの行をアニメーション化することです。

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

お役に立てれば。

于 2014-03-06T08:09:58.843 に答える