java 接口interface的使用

首先:创建一个接口类, 里面只有一个空方法,没有方法体:

package com.lp.scroll;

public interface SelectPoint{

    public void changeSelectedPoint(int position);
}


然后,在实现改接口的类中定义该接口中方法具体要做的事情:

package com.lp.scroll;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.lp.R;

public class ScrollPoints extends LinearLayout implements SelectPoint {
    private List<ImageView> points = new ArrayList<ImageView>();
    private LinearLayout pointBox;

    public ScrollPoints(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    public void initPoints(Context context, int count, int selected) {
        pointBox = new LinearLayout(context);
        
        for (int i = 0; i < count; i++) {
            ImageView slidePot = new ImageView(context);
            slidePot.setPadding(5, 5, 5, 5);

            if (i == selected) {
                slidePot.setBackgroundResource(R.drawable.slide_pot_selected);
            } else {
                slidePot.setBackgroundResource(R.drawable.slide_pot);
            }

            points.add(slidePot);
            pointBox.addView(slidePot);
        }

        addView(pointBox);
    }

    public void addPoint(Context context, int count){
        if(count > points.size()){
            ImageView slidePot = new ImageView(context);
            slidePot.setPadding(5, 5, 5, 5);
            points.add(slidePot);
            pointBox.addView(slidePot);
        }
    }
    
    @Override
    public void changeSelectedPoint(int position) {
        for (int i = 0; i < points.size(); i++) {
            ImageView point = points.get(i);
            if (i == position) {
                point.setBackgroundResource(R.drawable.slide_pot_selected);
            } else {
                point.setBackgroundResource(R.drawable.slide_pot);
            }
        }
    }

}

第三步:在触发该接口事件的类中定义一个方法,把接口实例传入:

package com.lp.scroll;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.Scroller;

import com.lp.R;
import com.lp.adapter.CategoryAdapter;

/**
 * 仿Launcher中的WorkSapce,可以左右滑动切换屏幕的类
 */
public class ScrollLayout extends ViewGroup {
    private static final String TAG = "ScrollLayout";
    private static final int CATEGORY_COUNT_PER_SCREEN = 9;
    private Scroller mScroller;
    private VelocityTracker mVelocityTracker;

    private int mCurScreen;
    private int mDefaultScreen = 0;

    private static final int TOUCH_STATE_REST = 0;
    private static final int TOUCH_STATE_SCROLLING = 1;

    private static final int SNAP_VELOCITY = 600;

    private int mTouchState = TOUCH_STATE_REST;
    private int mTouchSlop;
    private float mLastMotionX;
    private float mLastMotionY;
    private SelectPoint changePoint = null;
    private Map<String, Integer> categories;
    private boolean viewChanged = false;

    public ScrollLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        // TODO Auto-generated constructor stub
    }

    public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
        mScroller = new Scroller(context);
        // 默认显示第一屏
        mCurScreen = mDefaultScreen;
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed || viewChanged) {
            viewChanged = false;
            int childLeft = 0;
            final int childCount = getChildCount();

            for (int i = 0; i < childCount; i++) {
                final View childView = getChildAt(i);
                if (childView.getVisibility() != View.GONE) {
                    final int childWidth = childView.getMeasuredWidth();
                    childView.layout(childLeft, 0, childLeft + childWidth,
                            childView.getMeasuredHeight());
                    childLeft += childWidth;
                    // 很明显 0 - 320 | 320 - 640 | 640 - 960 ...(假设屏幕宽320)
                }
            }
        }
    }

    @Override
    public void addView(View child) {
        super.addView(child);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.e(TAG, "onMeasure");
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        final int width = MeasureSpec.getSize(widthMeasureSpec);
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if (widthMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException(
                    "ScrollLayout only canmCurScreen run at EXACTLY mode!");
        }

        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException(
                    "ScrollLayout only can run at EXACTLY mode!");
        }

        // The children are given the same width and height as the scrollLayout
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
        }
        // Log.e(TAG, "moving to screen "+mCurScreen);
        // x坐标 y坐标
        // 移动到第几屏
        scrollTo(mCurScreen * width, 0);
    }

    /**
     * According to the position of current layout scroll to the destination
     * page. 判断滑动的位置 如果大于当前屏中间的位置 则换屏 否则 仍然是这个屏 getScrollX x方向的偏移量
     */

    public void snapToDestination() {
        final int screenWidth = getWidth();
        // 判断
        final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;
        snapToScreen(destScreen);
    }

    public void snapToScreen(int whichScreen) {
        // get the valid layout page
        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
        if (getScrollX() != (whichScreen * getWidth())) {

            final int delta = whichScreen * getWidth() - getScrollX();
            // 开始滚动
            // x,y,x方向移动量,y方向移动量,滚动持续时间,负数往左滚
            mScroller.startScroll(getScrollX(), 0, delta, 0,
                    Math.abs(delta) * 2);
            mCurScreen = whichScreen;
            invalidate(); // Redraw the layout

            changePoint.changeSelectedPoint(mCurScreen);
        }
    }

    public void setToScreen(int whichScreen) {
        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
        mCurScreen = whichScreen;
        scrollTo(whichScreen * getWidth(), 0);
    }

    public int getCurScreen() {
        return mCurScreen;
    }

    public int getScreenCount() {
        return getChildCount();
    }

    // 只有当前LAYOUT中的某个CHILD导致SCROLL发生滚动,才会致使自己的COMPUTESCROLL被调用
    @Override
    public void computeScroll() {
        // TODO Auto-generated method stub
        Log.e(TAG, "computeScroll");
        // 如果返回true,表示动画还没有结束
        // 因为前面startScroll,所以只有在startScroll完成时 才会为false
        if (mScroller.computeScrollOffset()) {
            Log.e(TAG, mScroller.getCurrX() + "======" + mScroller.getCurrY());
            // 产生了动画效果 每次滚动一点
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        Log.e(TAG, "onTouchEvent start");
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);

        final int action = event.getAction();
        final float x = event.getX();
        final float y = event.getY();

        switch (action) {
        case MotionEvent.ACTION_DOWN:
            Log.e(TAG, "event down! " + mScroller.isFinished());
            // 如果屏幕的滚动动画没有结束 你就按下了 就结束动画
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
            }
            mLastMotionX = x;
            break;

        case MotionEvent.ACTION_MOVE:
            Log.e(TAG, "event move!");
            // 取得偏移量
            int deltaX = (int) (mLastMotionX - x);
            Log.e(TAG, "detaX: " + deltaX);
            mLastMotionX = x;
            // x方向的偏移量 y方向的偏移量
            scrollBy(deltaX, 0);
            break;

        case MotionEvent.ACTION_UP:
            Log.e(TAG, "event : up");
            // if (mTouchState == TOUCH_STATE_SCROLLING) {
            final VelocityTracker velocityTracker = mVelocityTracker;
            velocityTracker.computeCurrentVelocity(1000);
            int velocityX = (int) velocityTracker.getXVelocity();
            Log.e(TAG, "velocityX:" + velocityX);

            if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {
                // Fling enough to move left
                Log.e(TAG, "snap left");
                snapToScreen(mCurScreen - 1);
            } else if (velocityX < -SNAP_VELOCITY
                    && mCurScreen < getChildCount() - 1) {
                // Fling enough to move right
                Log.e(TAG, "snap right");
                snapToScreen(mCurScreen + 1);
            } else {
                // 一般都掉用这个
                snapToDestination();
            }
            if (mVelocityTracker != null) {
                mVelocityTracker.recycle();
                mVelocityTracker = null;
            }
            // }
            mTouchState = TOUCH_STATE_REST;
            break;
        case MotionEvent.ACTION_CANCEL:
            mTouchState = TOUCH_STATE_REST;
            break;
        }

        return true;
    }

    // 这个感觉没什么作用 不管true还是false 都是会执行onTouchEvent的 因为子view里面onTouchEvent返回false了
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        Log.e(TAG, "onInterceptTouchEvent-slop:" + mTouchSlop);

        final int action = ev.getAction();
        if ((action == MotionEvent.ACTION_MOVE)
                && (mTouchState != TOUCH_STATE_REST)) {
            return true;
        }

        final float x = ev.getX();
        final float y = ev.getY();

        switch (action) {
        case MotionEvent.ACTION_MOVE:
            Log.e(TAG, "onInterceptTouchEvent move");
            final int xDiff = (int) Math.abs(mLastMotionX - x);
            if (xDiff > mTouchSlop) {
                mTouchState = TOUCH_STATE_SCROLLING;

            }
            break;

        case MotionEvent.ACTION_DOWN:
            Log.e(TAG, "onInterceptTouchEvent down");
            mLastMotionX = x;
            mLastMotionY = y;
            Log.e(TAG, mScroller.isFinished() + "");
            mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
                    : TOUCH_STATE_SCROLLING;
            break;

        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            Log.e(TAG, "onInterceptTouchEvent up or cancel");
            mTouchState = TOUCH_STATE_REST;
            break;
        }
        Log.e(TAG, mTouchState + "====" + TOUCH_STATE_REST);
        return mTouchState != TOUCH_STATE_REST;
    }

    /**
     * @param chacgePoint
     *            the chacgePoint to set
     */
    public void setChacgePoint(SelectPoint changePoint) {
        this.changePoint = changePoint;
    }


    public void setCategories(Map<String, Integer> categories) {
        this.categories = categories;
    }

    public void initScreen(Activity activity, LayoutInflater inflater) {
        if (categories == null) {
            return;
        }

        Set<Entry<String, Integer>> entrySet = categories.entrySet();
        int i = 0;
        int totalScreenNum = categories.size() / CATEGORY_COUNT_PER_SCREEN;
        int currentScreen = 0;
        Map<String, Integer> oneScreenCategories = null;
        for (Iterator<Entry<String, Integer>> it = entrySet.iterator(); it
                .hasNext();) {

            // 9 category icons in one screen
            if (i % CATEGORY_COUNT_PER_SCREEN == 0) {
                currentScreen++;
                if (oneScreenCategories != null) {
                    GridView child = (GridView) inflater.inflate(
                            R.layout.single_screen, null);
                    child.setAdapter(new CategoryAdapter(activity,
                            oneScreenCategories));
                    addView(child);
                }
                oneScreenCategories = new LinkedHashMap<String, Integer>();
            }

            // create map for last category screen
            if (currentScreen > totalScreenNum + 1) {
                oneScreenCategories = new LinkedHashMap<String, Integer>();
            }

            // put every 9 category objects into one map
            Map.Entry<String, Integer> entry = (Entry<String, Integer>) it
                    .next();
            oneScreenCategories.put(entry.getKey(), entry.getValue());

            // add last category screen
            if (i == categories.size() - 1) {
                GridView child = (GridView) inflater.inflate(
                        R.layout.single_screen, null);
                child.setAdapter(new CategoryAdapter(activity,
                        oneScreenCategories));
                addView(child);
            }

            i++;
        }
    }

    public void addCategory(Activity activity, LayoutInflater inflater,
            String categoryName, Integer categoryIconId) {

        categories.put(categoryName, categoryIconId);

        CategoryAdapter adapter = (CategoryAdapter) ((GridView) getChildAt(getChildCount() - 1))
                .getAdapter();
        int categoryCount = adapter.getCount();

        if (categoryCount < CATEGORY_COUNT_PER_SCREEN) {
            // add to last screen
            adapter.addCategory(categoryName, categoryIconId);
            adapter.notifyDataSetChanged();
        } else {
            // create a new screen
            Map<String, Integer> categories = new LinkedHashMap<String, Integer>();
            categories.put(categoryName, categoryIconId);
            GridView child = (GridView) inflater.inflate(
                    R.layout.single_screen, null);
            child.setAdapter(new CategoryAdapter(activity, categories));
            addView(child);
        }
        viewChanged = true;
    }
}


最后:把接口实例set进触发接口事件的实例:

package com.lp;

import java.util.LinkedHashMap;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.lp.scroll.ScrollLayout;
import com.lp.scroll.ScrollPoints;

public class D_multiScreenActivity extends Activity implements OnClickListener {
    private LayoutInflater mInflater;
    private ScrollLayout mScrollLayout;
    private ScrollPoints mScrollPoints;

    private Button btnAddCategory;
    private Map<String, Integer> categories;
    private int num = 0;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mInflater = LayoutInflater.from(this);
        mScrollLayout = (ScrollLayout) findViewById(R.id.ScrollLayoutTest);
        mScrollPoints = (ScrollPoints) findViewById(R.id.scrollPoints);
        btnAddCategory = (Button) findViewById(R.id.addCategory);
        btnAddCategory.setOnClickListener(this);

        // fake data
        categories = new LinkedHashMap<String, Integer>();
        for (int i = 0; i < 45; i++) {
            categories.put("my cate" + i, R.drawable.icon);
        }

        // initial category by map
        mScrollLayout.setCategories(categories);
        mScrollLayout.initScreen(this, mInflater);

        // set interface
        mScrollLayout.setChacgePoint(mScrollPoints);


        // add footer points
        mScrollPoints.initPoints(this, mScrollLayout.getScreenCount(),
                mScrollLayout.getCurScreen());

    }

    @Override
    public void onClick(View v) {
        num++;
        mScrollLayout.addCategory(D_multiScreenActivity.this,
                mInflater, "add cat" + num, R.drawable.icon);
        mScrollLayout.snapToScreen(mScrollLayout.getScreenCount() - 1);

        mScrollPoints.addPoint(D_multiScreenActivity.this,
                mScrollLayout.getScreenCount());
    }
}

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭