Android Open Source - ChessBoardLayout Chess Board Layout






From Project

Back to project page ChessBoardLayout.

License

The source code is released under:

Apache License

If you think the Android project ChessBoardLayout listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.jungkai.chessboardlayout;
/*  ww w .  j a v a  2 s  .co m*/
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.view.AccessibilityDelegateCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;

import java.util.ArrayList;

public class ChessBoardLayout extends AdapterView<BaseAdapter> {

    public static final int DEFAULT_COL_COUNT = 2;

    public static final int TOUCH_MODE_NONE = -1;

    public static final int TOUCH_MODE_DOWN = 0;

    public static final int TOUCH_MODE_TAP = 1;

    public static final int TOUCH_MODE_DONE_WAITING = 3;

    private Context context;

    private ArrayList<View> scrapViews;

    private SparseArray<Integer> rowHeight;

    private BaseAdapter adapter;

    private int colCount;

    private boolean isDataChanged;

    private int itemCount;

    private int colSpacing;

    private int rowSpacing;

    private int childWidth;

    private int selectedPosition;

    private View selectedView;

    private int touchMode = TOUCH_MODE_NONE;

    private CheckForLongPress pendingCheckForLongPress;

    private CheckForTap pendingCheckForTap;

    private Runnable touchModeReset;

    private PerformClick performClick;

    AccessibilityManager accessibilityManager;

    private AdapterDataSetObserver dataSetObserver;

    private int totalWidth;

    private BoardItemAccessibilityDelegate accessbilityDeledate;

    enum FocusDirection {
        FOCUS_UP, FOCUS_DOWN
    }

    public ChessBoardLayout(Context context) {
        super(context);
        this.context = context;
        init(null);
    }

    public ChessBoardLayout(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
        this.context = context;
        init(attrs);
    }

    public ChessBoardLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        accessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);

        setWillNotDraw(true);
        setClickable(true);
        setFocusable(true);

        if (attrs != null) {

            TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ChessBoardLayout);

            colCount = a.getInt(R.styleable.ChessBoardLayout_colCount, DEFAULT_COL_COUNT);

            colSpacing = a.getDimensionPixelSize(R.styleable.ChessBoardLayout_colSpacing, 0);

            rowSpacing = a.getDimensionPixelSize(R.styleable.ChessBoardLayout_rowSpacing, 0);

            a.recycle();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int maxHeight = Integer.MIN_VALUE;
        int totalHeight = 0, rowIdx = 0;

        final int horizontalPadding = getPaddingLeft() + getPaddingRight();

        totalWidth = MeasureSpec.getSize(widthMeasureSpec);

        final int availableWidth = totalWidth - horizontalPadding;

        final int verticalPadding = getPaddingTop() + getPaddingBottom();

        if (rowHeight == null) {
            rowHeight = new SparseArray<Integer>();
        } else {
            rowHeight.clear();
        }

        if (adapter == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }

        if (colCount < 1) {
            throw new IllegalStateException("colCount should be equals or more than 1");
        }

        if (scrapViews == null) {
            scrapViews = new ArrayList<View>(adapter.getCount());
        }

        childWidth = (availableWidth - (colSpacing * colCount - 1)) / colCount;

        itemCount = adapter.getCount();

        for (int i = 0; i < adapter.getCount(); i++) {
            View child = obtainView(i);

            final int childHeight = child.getMeasuredHeight();

            maxHeight = Math.max(maxHeight, childHeight);

            if (i > 0 && i % colCount == colCount - 1) {
                rowHeight.put(rowIdx, maxHeight);
                totalHeight += maxHeight;

                maxHeight = Integer.MIN_VALUE;
                rowIdx++;
            } else if (i == adapter.getCount() - 1) {
                rowHeight.put(rowIdx, maxHeight);
                totalHeight += maxHeight;
            }
        }

        int rowCount;

        if (adapter.getCount() > 0) {
            rowCount = scrapViews.size() / colCount + ((scrapViews.size() % colCount == 0) ? 0 : 1);
            totalHeight = totalHeight + (rowCount - 1) * rowSpacing;
        }

        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
        } else {
            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), verticalPadding + totalHeight);
        }
    }

    private View obtainView(int position) {
        View child;
        if (scrapViews.size() != 0 && scrapViews.size() > position) {
            child = scrapViews.get(position);
        } else {
            child = adapter.getView(position, null, this);

            LayoutParams p = getChildLayoutParams(child);
            measureChildIfNeeded(child, p);

            scrapViews.add(position, child);
        }

        if (ViewCompat.getImportantForAccessibility(child) == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            ViewCompat.setImportantForAccessibility(child, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
        }

        if (accessibilityManager.isEnabled()) {
            accessbilityDeledate = new BoardItemAccessibilityDelegate();
            ViewCompat.setAccessibilityDelegate(child, accessbilityDeledate);
        }

        return child;
    }

    private LayoutParams getChildLayoutParams(View child) {
        LayoutParams p = child.getLayoutParams();

        if (p == null) {
            p = generateDefaultLayoutParams();
            child.setLayoutParams(p);
        }
        return p;
    }

    private void measureChildIfNeeded(View child, LayoutParams p) {
        int childHeightSpec = getChildMeasureSpec(
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
        int childWidthSpec = getChildMeasureSpec(
                MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), 0, p.width);

        child.measure(childWidthSpec, childHeightSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (adapter != null && adapter.getCount() > 0 && isDataChanged) {

            final int paddingStart = getPaddingLeft();
            final int paddingTop = getPaddingTop();

            int rowIdx = -1;

            removeAllViewsInLayout();

            for (int i = 0; i < adapter.getCount(); i++) {
                View child = obtainView(i);

                int leftIdx = i % colCount;

                if (leftIdx == 0) {
                    rowIdx++;
                }

                LayoutParams p = child.getLayoutParams();

                if (p == null) {
                    p = generateDefaultLayoutParams();
                }

                addViewInLayout(child, i, p, true);

                int start;

                if (LayoutUtils.isLayoutRTL(context)) {
                    start = totalWidth - paddingStart - ((leftIdx + 1) * child.getMeasuredWidth());
                } else {
                    start = paddingStart + (leftIdx * child.getMeasuredWidth());
                }

                int topWithoutPadding = 0;

                for (int j = 0; j < rowIdx; j++) {
                    topWithoutPadding += rowHeight.get(j);
                }

                int top = paddingTop + topWithoutPadding;

                if (leftIdx > 0) {
                    if (LayoutUtils.isLayoutRTL(context)) {
                        start -= colSpacing * leftIdx;
                    } else {
                        start += colSpacing * leftIdx;
                    }
                }

                if (rowIdx > 0) {
                    top += rowSpacing * rowIdx;
                }
                child.layout(start, top, start + child.getMeasuredWidth(), top + rowHeight.get(rowIdx));
            }

            isDataChanged = false;
        }
    }

    public void setRowSpacing(int rowSpacing) {
        boolean needRequest = this.rowSpacing != rowSpacing;
        this.rowSpacing = rowSpacing;
        requestLayoutIfNeeded(needRequest);
    }

    public int getRowSpacing() {
        return this.rowSpacing;
    }

    public void setColSpacing(int colSpacing) {
        boolean needRequest = this.colSpacing != colSpacing;
        this.colSpacing = colSpacing;
        requestLayoutIfNeeded(needRequest);
    }

    public int getColSpacing() {
        return this.colSpacing;
    }

    public void setColCount(int colCount) {
        boolean needRequest = this.colCount != colCount;
        this.colCount = colCount;
        requestLayoutIfNeeded(needRequest);
    }

    public int getColCount() {
        return this.colCount;
    }

    private void requestLayoutIfNeeded(boolean updateFlag) {
        if (updateFlag) {
            isDataChanged = true;
            requestLayout();
        }
    }

    @Override
    public View getSelectedView() {
        return (scrapViews != null && selectedPosition >= 0 && selectedPosition < scrapViews.size()) ? scrapViews.get(selectedPosition) : null;
    }

    @Override
    public void setSelection(int position) {
        selectedPosition = position;
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new LayoutParams(p);
    }

    @Override
    protected boolean checkLayoutParams(LayoutParams p) {
        return p instanceof LayoutParams;
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    public BaseAdapter getAdapter() {
        return adapter;
    }

    @Override
    public void setAdapter(BaseAdapter adapter) {
        if (this.adapter != null && dataSetObserver != null) {
            this.adapter.unregisterDataSetObserver(dataSetObserver);
        }
        if (scrapViews != null) {
            scrapViews.clear();
        }

        this.adapter = adapter;

        selectedPosition = INVALID_POSITION;
        touchMode = TOUCH_MODE_NONE;

        if (this.adapter != null) {

            dataSetObserver = new AdapterDataSetObserver();

            this.adapter.registerDataSetObserver(dataSetObserver);

            isDataChanged = true;

            setSelection(0);
        }

        requestLayout();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (adapter != null && dataSetObserver != null) {
            adapter.unregisterDataSetObserver(dataSetObserver);
            dataSetObserver = null;
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        if (adapter != null && dataSetObserver == null) {
            dataSetObserver = new AdapterDataSetObserver();
            adapter.registerDataSetObserver(dataSetObserver);

            isDataChanged = true;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return isClickable() || isLongClickable();
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {

                selectedPosition = getPositionFromCoord((int) event.getX(), (int) event.getY());
                selectedView = getChildAt(selectedPosition);
                if (selectedPosition != INVALID_POSITION) {

                    clearSelectionState();

                    if ((selectedPosition >= 0) && getAdapter().isEnabled(selectedPosition)) {

                        touchMode = TOUCH_MODE_DOWN;

                        if (pendingCheckForTap == null) {
                            pendingCheckForTap = new CheckForTap();
                        }
                        postDelayed(pendingCheckForTap, ViewConfiguration.getTapTimeout());
                    }
                }
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                switch (touchMode) {
                    case TOUCH_MODE_DOWN:
                    case TOUCH_MODE_TAP:
                    case TOUCH_MODE_DONE_WAITING:
                        final float x = event.getX();
                        final float y = event.getY();
                        if (getPositionFromCoord((int) x, (int) y) != selectedPosition) {
                            if (selectedView != null) {
                                selectedView.setPressed(false);
                                touchMode = TOUCH_MODE_NONE;
                                removeCallbacks(touchMode == TOUCH_MODE_DOWN ?
                                        pendingCheckForTap : pendingCheckForLongPress);
                            }

                        }
                }
                break;
            }

            case MotionEvent.ACTION_UP: {
                switch (touchMode) {
                    case TOUCH_MODE_DOWN:
                    case TOUCH_MODE_TAP:
                    case TOUCH_MODE_DONE_WAITING:
                        if (selectedView != null) {
                            if (touchMode != TOUCH_MODE_DOWN) {
                                selectedView.setPressed(false);
                            }

                            if (performClick == null) {
                                performClick = new PerformClick();
                            }

                            final PerformClick performClick = this.performClick;
                            performClick.rememberWindowAttachCount();

                            if (touchMode == TOUCH_MODE_DOWN || touchMode == TOUCH_MODE_TAP) {
                                removeCallbacks(touchMode == TOUCH_MODE_DOWN ?
                                        pendingCheckForTap : pendingCheckForLongPress);

                                touchMode = TOUCH_MODE_TAP;

                                selectedView.setPressed(true);

                                if (touchModeReset != null) {
                                    removeCallbacks(touchModeReset);
                                }

                                touchModeReset = new Runnable() {
                                    @Override
                                    public void run() {
                                        touchModeReset = null;
                                        touchMode = TOUCH_MODE_NONE;
                                        selectedView.setPressed(false);
                                        if (getWindowToken() != null) {
                                            performClick.run();
                                        }
                                    }
                                };
                                postDelayed(touchModeReset,
                                        ViewConfiguration.getPressedStateDuration());
                            } else {
                                performClick.run();
                            }
                        }

                        touchMode = TOUCH_MODE_NONE;
                        break;
                }
            }

            case MotionEvent.ACTION_CANCEL: {
                if (touchMode != TOUCH_MODE_NONE) {
                    touchMode = TOUCH_MODE_NONE;
                    final View child = this.getChildAt(selectedPosition);
                    if (child != null) {
                        child.setPressed(false);
                    }
                    removeCallbacks(pendingCheckForLongPress);
                }

                break;
            }

            case MotionEvent.ACTION_POINTER_UP: {
                break;
            }

            case MotionEvent.ACTION_POINTER_DOWN: {
                break;
            }
        }

        return true;
    }

    final class CheckForTap implements Runnable {
        @Override
        public void run() {
            if (touchMode == TOUCH_MODE_DOWN) {
                touchMode = TOUCH_MODE_TAP;
                final View child = getChildAt(selectedPosition);
                if (child != null && !child.hasFocusable()) {
                    child.setPressed(true);
                    refreshDrawableState();

                    final boolean longClickable = isLongClickable();

                    if (longClickable) {
                        if (pendingCheckForLongPress == null) {
                            pendingCheckForLongPress = new CheckForLongPress();
                        }
                        pendingCheckForLongPress.rememberWindowAttachCount();
                        postDelayed(pendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
                    } else {
                        touchMode = TOUCH_MODE_DONE_WAITING;
                    }
                } else {
                    touchMode = TOUCH_MODE_DONE_WAITING;
                }
            }
        }


    }

    final class CheckForLongPress extends WindowRunnnable implements Runnable {
        @Override
        public void run() {
            final View child = getChildAt(selectedPosition);
            if (child != null) {
                final long longPressId = adapter.getItemId(selectedPosition);
                boolean handled = false;
                if (sameWindow())
                    handled = performLongPress(child, selectedPosition, longPressId);

                if (handled) {
                    touchMode = TOUCH_MODE_NONE;
                    child.setPressed(false);
                } else {
                    touchMode = TOUCH_MODE_DONE_WAITING;
                }
            }
        }
    }

    final class PerformClick extends WindowRunnnable implements Runnable {

        @Override
        public void run() {
            if (adapter != null && selectedPosition != INVALID_POSITION && sameWindow()) {
                final View view = getChildAt(selectedPosition);
                if (view != null) {
                    performItemClick(view, selectedPosition, adapter.getItemId(selectedPosition));
                }
            }
        }
    }

    private class WindowRunnnable {
        private int mOriginalAttachCount;

        public void rememberWindowAttachCount() {
            mOriginalAttachCount = getWindowAttachCount();
        }

        public boolean sameWindow() {
            return getWindowAttachCount() == mOriginalAttachCount;
        }
    }

    private boolean performLongPress(final View child,
                                     final int longPressPosition, final long longPressId) {

        boolean handled = false;
        if (getOnItemLongClickListener() != null) {
            handled = getOnItemLongClickListener().onItemLongClick(this, child,
                    longPressPosition, longPressId);
        }

        if (handled) {
            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        }
        return handled;
    }

    //x, y??? ????? ?? ???.
    private int getPositionFromCoord(int x, int y) {
        Rect viewFrame = new Rect();

        final int count = getChildCount();
        for (int i = count - 1; i >= 0; i--) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.VISIBLE) {
                child.getHitRect(viewFrame);
                if (viewFrame.contains(x, y)) {
                    return i;
                }
            }
        }
        return INVALID_POSITION;
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (isConfirmKey(keyCode)) {
            if (!isEnabled()) {
                return true;
            }
            if (isClickable() &&
                    selectedPosition >= 0 && adapter != null && selectedPosition < adapter.getCount()) {

                final View view = getChildAt(selectedPosition);
                if (view != null) {
                    performItemClick(view, selectedPosition, adapter.getItemId(selectedPosition));
                    view.setPressed(false);
                }
                return true;
            }
        }
        return super.onKeyUp(keyCode, event);
    }

    public static final boolean isConfirmKey(int keyCode) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_ENTER:
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (getChildCount() <= 0) {
            return super.onKeyDown(keyCode, event);
        }

        boolean handled = false;
        int action = event.getAction();

        if (action != KeyEvent.ACTION_UP) {
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    handled = updateSelection(FocusDirection.FOCUS_DOWN);
                    break;
                case KeyEvent.KEYCODE_DPAD_UP:
                    handled = updateSelection(FocusDirection.FOCUS_UP);
                    break;
                case KeyEvent.KEYCODE_DPAD_CENTER:
                case KeyEvent.KEYCODE_ENTER:
                    handled = keyPressed();
                    break;
            }
        }

        if (handled) {
            return true;
        }

        switch (action) {
            case KeyEvent.ACTION_DOWN:
                return super.onKeyDown(keyCode, event);
            case KeyEvent.ACTION_UP:
                return super.onKeyUp(keyCode, event);
            default:
                return false;
        }
    }

    public boolean keyPressed() {
        if (!isEnabled() || !isClickable()) {
            return false;
        }

        if (isFocused()) {

            final View v = getChildAt(selectedPosition);

            if (v != null) {
                if (v.hasFocusable()) return false;
                v.setPressed(true);
            }

            final boolean longClickable = isLongClickable();

            if (longClickable) {
                if (pendingCheckForLongPress == null) {
                    pendingCheckForLongPress = new CheckForLongPress();
                }
                pendingCheckForLongPress.rememberWindowAttachCount();
                postDelayed(pendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
            }

            return true;
        } else {
            return false;
        }
    }

    private boolean updateSelection(FocusDirection direction) {
        getChildAt(selectedPosition).setSelected(false);

        if (direction == FocusDirection.FOCUS_UP) {
            if (selectedPosition == 0) {
                return false;
            }
            selectedPosition--;
        } else {
            if (selectedPosition == getChildCount() - 1) {
                return false;
            }
            selectedPosition++;
        }

        getChildAt(selectedPosition).setSelected(true);
        return true;
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);

        if (getChildCount() <= 0) {
            return ;
        }

        if (gainFocus && !isInTouchMode()) {
            View selectedView = getChildAt(selectedPosition);
            selectedView.setSelected(true);
        } else {
            clearSelectionState();
        }
    }

    private void clearSelectionState() {
        for (int i = 0; i < getChildCount(); i++) {
            getChildAt(i).setSelected(false);
        }
    }

    //notifydatasetchanged? ??? ?????? ??
    class AdapterDataSetObserver extends DataSetObserver {

        @Override
        public void onChanged() {
            isDataChanged = true;
            requestLayout();
        }

        @Override
        public void onInvalidated() {
            isDataChanged = true;
            selectedPosition = INVALID_POSITION;
            requestLayout();
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        if (getChildCount() > 0) {
            scrapViews.clear();
            isDataChanged = true;
        }
    }

    class BoardItemAccessibilityDelegate extends AccessibilityDelegateCompat {
        @Override
        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
            super.onInitializeAccessibilityNodeInfo(host, info);

            int position = getPositionForView(host);
            onInitializeAccessibilityNodeInfoForItem(position, info);
        }

        @Override
        public boolean performAccessibilityAction(View host, int action, Bundle args) {
            if (super.performAccessibilityAction(host, action, args)) {
                return true;
            }

            final int position = getPositionForView(host);
            final BaseAdapter adapter = getAdapter();

            if ((position == INVALID_POSITION) || (adapter == null)) {
                return false;
            }

            if (!isEnabled() || !adapter.isEnabled(position)) {
                return false;
            }

            final long id = getItemIdAtPosition(position);

            switch (action) {
                case AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION: {
                    if (selectedPosition == position) {
                        setSelection(INVALID_POSITION);
                        return true;
                    }
                } return false;
                case AccessibilityNodeInfoCompat.ACTION_SELECT: {
                    if (selectedPosition != position) {
                        setSelection(position);
                        return true;
                    }
                } return false;
                case AccessibilityNodeInfoCompat.ACTION_CLICK: {
                    if (isClickable()) {
                        return performItemClick(host, position, id);
                    }
                } return false;
                case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK: {
                    if (isLongClickable()) {
                        return performLongPress(host, position, id);
                    }
                } return false;
            }

            return false;
        }

    }

    public void onInitializeAccessibilityNodeInfoForItem(
            int position, AccessibilityNodeInfoCompat info) {
        if (position == INVALID_POSITION || adapter == null) {
            return;
        }

        if (!isEnabled() || !adapter.isEnabled(position)) {
            info.setEnabled(false);
            return;
        }

        if (position == selectedPosition) {
            info.setSelected(true);
            info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION);
        } else {
            info.addAction(AccessibilityNodeInfoCompat.ACTION_SELECT);
        }

        if (isClickable()) {
            info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
            info.setClickable(true);
        }

        if (isLongClickable()) {
            info.addAction(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK);
            info.setLongClickable(true);
        }
    }
}




Java Source Code List

com.jungkai.chessboardlayout.ApplicationTest.java
com.jungkai.chessboardlayout.ChessBoardLayout.java
com.jungkai.chessboardlayout.LayoutUtils.java
com.kai.sample.app.ApplicationTest.java
com.kai.sample.app.Fruit.java
com.kai.sample.app.MainActivity.java