Code example for AbsListView

Methods: AbsListView.invalidate, getAdapter, getWidth, onTouchEvent

0
    	 
    	//System.out.println("State: " + state); 
        switch (state) {
            case STATE_NONE:
                mHandler.removeCallbacks(mScrollFade);
                mList.invalidate();
                break; 
            case STATE_VISIBLE:
                if (mState != STATE_VISIBLE) { // Optimization
                    resetThumbPos(); 
                } 
                // Fall through 
            case STATE_DRAGGING:
                mHandler.removeCallbacks(mScrollFade);
                break; 
            case STATE_EXIT:
                int viewWidth = mList.getWidth();
                mList.invalidate(viewWidth - mThumbW, mThumbY, viewWidth, mThumbY + mThumbH);
                break; 
        } 
        mState = state;
    } 
     
    public int getState() { 
        return mState;
    } 
     
    private void resetThumbPos() { 
        final int viewWidth = mList.getWidth();
        // Bounds are always top right. Y coordinate get's translated during draw 
        // For reference, the thumb itself is approximately 50% as wide as the underlying graphic 
        // so 1/6th of the width means the thumb is approximately 1/12 the width. 
        mThumbW = (int)(mLargeTextScaledSize * 2.5); // viewWidth / 6 ; //mOverlaySize *3/4 ; //64; //mCurrentThumb.getIntrinsicWidth();
        mThumbH = (int)(mLargeTextScaledSize * 2.5); //viewWidth / 6 ; //mOverlaySize *3/4; //52; //mCurrentThumb.getIntrinsicHeight();
 
        mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
        mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX);
    } 
     
    private void useThumbDrawable(Drawable drawable) {
        mThumbDrawable = drawable;
        // Can't use the view width yet, because it has probably not been set up 
        // so we just use the native width. It will be set later when we come to 
        // actually draw it. 
        mThumbW = mThumbDrawable.getIntrinsicWidth();
        mThumbH = mThumbDrawable.getIntrinsicHeight();
        mChangedBounds = true;
    } 
 
    private void init(Context context) {
        // Get both the scrollbar states drawables 
        final Resources res = context.getResources();
        useThumbDrawable(res.getDrawable( R.drawable.scrollbar_handle_accelerated_anim2));
         
        mOverlayDrawable = res.getDrawable( R.drawable.menu_submenu_background);
         
        mScrollCompleted = true;
 
        getSections(); 
         
        mOverlayPos = new RectF();
        mScrollFade = new ScrollFade();
        mPaint = new TextPaint();
        mPaint.setAntiAlias(true);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(mOverlaySize / 3);
        TypedArray ta = context.getTheme().obtainStyledAttributes(new int[] { 
                android.R.attr.textColorPrimary });
        ColorStateList textColor = ta.getColorStateList(ta.getIndex(0));
        int textColorNormal = textColor.getDefaultColor();
        mPaint.setColor(textColorNormal);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
         
        mState = STATE_NONE;
 
        // Send a fake onSizeChanged so that overlay position is correct if 
        // this is called after Activity is stable 
        final int w = mList.getWidth();
        final int h = mList.getHeight();
        onSizeChanged(w,h,w,h);
    } 
     
    void stop() { 
        setState(STATE_NONE);
        // No need for these any more. 
        mOverlayDrawable = null;
        mThumbDrawable = null;
    } 
     
    boolean isVisible() { 
        return !(mState == STATE_NONE);
    } 
     
    public void draw(final Canvas canvas) {
         
        if (mState == STATE_NONE) {
            // No need to draw anything 
            return; 
        } 
 
        final int y = mThumbY;
        final int viewWidth = mList.getWidth();
        final FastScroller.ScrollFade scrollFade = mScrollFade;
 
        int alpha = -1;
        if (mState == STATE_EXIT) {
            alpha = scrollFade.getAlpha();
            if (alpha < ScrollFade.ALPHA_MAX / 2) {
                mThumbDrawable.setAlpha(alpha * 2);
            } 
            int left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX;
            mThumbDrawable.setBounds(left, 0, viewWidth, mThumbH);
            mChangedBounds = true;
        } 
 
        canvas.translate(0, y);
        mThumbDrawable.draw(canvas);
        canvas.translate(0, -y);
 
        // If user is dragging the scroll bar, draw the alphabet overlay 
        if (mState == STATE_DRAGGING && mDrawOverlay) {
            final TextPaint paint = mPaint;
            float descent = paint.descent();
            final RectF rectF = mOverlayPos;
 
            // Work out what we actually need to draw 
            boolean has2Lines;
            String line1;
            String line2 = "";
            // If there is no V2 data, use the V1 data 
            if (mSectionTextV2 == null) {
            	has2Lines = false;
            	line1 = mSectionTextV1;
            } else { 
            	// If using V2 data, make sure line 1 is a valid straing 
            	if (mSectionTextV2[0] == null)
            		line1 = "";
            	else 
            		line1 = mSectionTextV2[0];
            	// Check if line 2 is present  
            	if (mSectionTextV2.length > 1 && mSectionTextV2[1] != null && !mSectionTextV2[1].equals("")) {
            		has2Lines = true;
            		line2 = mSectionTextV2[1];
            	} else { 
                	has2Lines = false;            		
            	} 
            } 
 
            // If there are two lines, expand the box 
            if (has2Lines) {
            	Rect pos = mOverlayDrawable.getBounds();
            	Rect posSave = new Rect(pos);
            	pos.set(pos.left, pos.top, pos.right, pos.bottom + pos.height()/2);
            	mOverlayDrawable.setBounds(pos);
                mOverlayDrawable.draw(canvas);
            	mOverlayDrawable.setBounds(posSave);            	
            } else { 
                mOverlayDrawable.draw(canvas);            	
            } 
 
            // Draw the first line 
            final String text1 = TextUtils.ellipsize(line1, paint, (mOverlayPos.right - mOverlayPos.left) * 0.8f, TextUtils.TruncateAt.END).toString();
            canvas.drawText(text1, (int) (rectF.left + rectF.right) / 2,
            					  // Base of text at: (middle) + (half text height) - descent : so it is vertically centred 
                    			  (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 6 - descent, 
                    			  paint);
 
            if (has2Lines) {
            	// Draw the second line, but smaller than first 
                float s = paint.getTextSize();
                paint.setTextSize(s * 0.7f);
                final String text2 = TextUtils.ellipsize(line2, paint, (mOverlayPos.right - mOverlayPos.left) * 0.8f, TextUtils.TruncateAt.END).toString();
                canvas.drawText(text2, (int) (rectF.left + rectF.right) / 2,
  					  // Base of text at: (middle) + (half text height) - descent : so it is vertically centred 
          			  (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 6 + s, 
          			  paint);
                paint.setTextSize(s);            	
            } 
 
        } else if (mState == STATE_EXIT) {
            if (alpha == 0) { // Done with exit
                setState(STATE_NONE);
            } else { 
                mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);            
            } 
        } 
    } 
 
    void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (mThumbDrawable != null) {
            mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH);
        } 
        final RectF pos = mOverlayPos;
        // Original: width was equal to height, controlled by mOverlaySize. 
        //    pos.left = (w - mOverlaySize) / 2; 
        //    pos.right = pos.left + mOverlaySize; 
        // 
        // Now, Make it 75% of total available space 
        pos.left = (w / 8);
        pos.right = pos.left + w * 3 / 4;
        pos.top = h / 10; // 10% from top
        pos.bottom = pos.top + mOverlaySize;
        if (mOverlayDrawable != null) {
            mOverlayDrawable.setBounds((int) pos.left, (int) pos.top,
                (int) pos.right, (int) pos.bottom);
        } 
    } 
     
    void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 
            int totalItemCount) {
        // Are there enough pages to require fast scroll? Recompute only if total count changes 
        if (mItemCount != totalItemCount && visibleItemCount > 0) {
            mItemCount = totalItemCount;
            mLongList = mItemCount / visibleItemCount >= MIN_PAGES;
        } 
        if (!mLongList) {
            if (mState != STATE_NONE) {
                setState(STATE_NONE);
            } 
            return; 
        } 
        if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING ) {
            mThumbY = ((mList.getHeight() - mThumbH) * firstVisibleItem) 
                    / (totalItemCount - visibleItemCount);
            if (mChangedBounds) {
                resetThumbPos(); 
                mChangedBounds = false;
            } 
        } 
        mScrollCompleted = true;
        if (firstVisibleItem == mVisibleItem) {
            return; 
        } 
        mVisibleItem = firstVisibleItem;
        if (mState != STATE_DRAGGING) {
            setState(STATE_VISIBLE);
            mHandler.postDelayed(mScrollFade, 1500);
        } 
    } 
 
    private void getSections() { 
        Adapter adapter = mList.getAdapter();
        mSectionIndexerV1 = null;
        mSectionIndexerV2 = null;
        if (adapter instanceof HeaderViewListAdapter) {
            mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount();
            adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
        } 
        if (mList instanceof ExpandableListView) {
            ExpandableListAdapter expAdapter = ((ExpandableListView)mList).getExpandableListAdapter();
            if (expAdapter instanceof SectionIndexer) {
                mSectionIndexerV1 = (SectionIndexer) expAdapter;
                mListAdapter = (BaseAdapter) adapter;
                mSections = mSectionIndexerV1.getSections();
            } else if (expAdapter instanceof SectionIndexerV2) {
                mSectionIndexerV2 = (SectionIndexerV2) expAdapter;
                mListAdapter = (BaseAdapter) adapter;            	
            } 
        } else { 
            if (adapter instanceof SectionIndexer) {
                mListAdapter = (BaseAdapter) adapter;
                mSectionIndexerV1 = (SectionIndexer) adapter;
                mSections = mSectionIndexerV1.getSections();
            } else if (adapter instanceof SectionIndexerV2) {
                    mListAdapter = (BaseAdapter) adapter;
                    mSectionIndexerV2 = (SectionIndexerV2) adapter;
            } else { 
                mListAdapter = (BaseAdapter) adapter;
                mSections = new String[] { " " };
            } 
        } 
    } 
 
	private void scrollTo(float position) {
		int count = mList.getCount();
		mScrollCompleted = false;
		final Object[] sections = mSections;
		int sectionIndex;
 
		int index = (int) (position * count);
		if (mList instanceof ListView) { // This INCLUDES ExpandableListView
			((ListView) mList).setSelectionFromTop(index + mListOffset, 0);
		} else { 
			mList.setSelection(index + mListOffset);
		} 
		if (mSectionIndexerV2 != null) {
			mSectionTextV2 = mSectionIndexerV2.getSectionTextForPosition(index);
		} else { 
			if (sections != null && sections.length > 1) {
				sectionIndex = mSectionIndexerV1.getSectionForPosition(index);
				if (sectionIndex >=0 && sectionIndex < sections.length)
					mSectionTextV1 = sections[sectionIndex].toString();
				else 
					mSectionTextV1 = null;					
			} else { 
				sectionIndex = -1;
				mSectionTextV1 = null;
			} 
		} 
 
		if ( (mSectionTextV2 != null ) || (mSectionTextV1 != null && mSectionTextV1.length() > 0)) {
			mDrawOverlay = true; //(mSectionText.length() != 1 || mSectionText.charAt(0) != ' ')
							; //&& sectionIndex < sections.length; 
		} else { 
			mDrawOverlay = false;
		} 
	} 
 
    private void cancelFling() { 
        // Cancel the list fling 
        MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
        mList.onTouchEvent(cancelFling);
        cancelFling.recycle();
    } 
     
    boolean onInterceptTouchEvent(MotionEvent ev) {
        if (mState > STATE_NONE && ev.getAction() == MotionEvent.ACTION_DOWN) {
            if (ev.getX() > mList.getWidth() - mThumbW && ev.getY() >= mThumbY &&
                    ev.getY() <= mThumbY + mThumbH) {
                setState(STATE_DRAGGING);
                return true; 
            } 
        } 
        return false; 
    } 
 
    boolean onTouchEvent(MotionEvent me) {
        if (mState == STATE_NONE) {
            return false; 
        } 
        if (me.getAction() == MotionEvent.ACTION_DOWN) {
            if (me.getX() > mList.getWidth() - mThumbW
                    && me.getY() >= mThumbY 
                    && me.getY() <= mThumbY + mThumbH) {
                 
                setState(STATE_DRAGGING);
                if (mListAdapter == null && mList != null) {