浏览代码

1.删除折叠控件及其引用;
2.优化设备列表适配器;
3.修改设备列表项布局;
4.添加若干SVG图标。

Yumin 6 年之前
父节点
当前提交
acaa032f44

+ 27 - 0
app/src/main/java/cn/minbb/producttester/adapter/DeviceListAdapter.java

@@ -8,6 +8,8 @@ import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 
+import com.joanzapata.iconify.widget.IconTextView;
+
 import java.util.List;
 
 import butterknife.BindView;
@@ -59,6 +61,8 @@ public class DeviceListAdapter extends BaseAdapter {
         // 设置控件数据
         viewHolder.deviceName.setText(itemBean.deviceName);
         viewHolder.deviceAddress.setText(itemBean.deviceAddress);
+        viewHolder.deviceStatus.setText(itemBean.deviceStatus);
+        viewHolder.deviceTip.setText(itemBean.deviceTip);
         return convertView;
     }
 
@@ -69,6 +73,10 @@ public class DeviceListAdapter extends BaseAdapter {
         TextView deviceName;
         @BindView(R.id.deviceAddress)
         TextView deviceAddress;
+        @BindView(R.id.deviceStatus)
+        IconTextView deviceStatus;
+        @BindView(R.id.deviceTip)
+        TextView deviceTip;
 
         ViewHolder(View view) {
             ButterKnife.bind(this, view);
@@ -80,10 +88,29 @@ public class DeviceListAdapter extends BaseAdapter {
         public BluetoothDevice device;
         String deviceName;
         String deviceAddress;
+        String deviceStatus;
+        String deviceTip;
 
         public ItemBean(BluetoothDevice device) {
+            this.device = device;
             this.deviceName = device.getName();
             this.deviceAddress = device.getAddress();
+            switch (device.getBondState()) {
+                case BluetoothDevice.BOND_NONE:
+                    // 未配对
+                    this.deviceStatus = "{fa-unlink}";
+                    this.deviceTip = "点击配对";
+                    break;
+                case BluetoothDevice.BOND_BONDING:
+                    // 配对中
+                    break;
+                case BluetoothDevice.BOND_BONDED:
+                    // 已配对
+                    this.deviceStatus = "{fa-link} 已配对";
+                    this.deviceTip = "点击连接";
+                    break;
+                default:
+            }
         }
     }
 }

+ 0 - 611
app/src/main/java/cn/minbb/producttester/controls/BaseFoldingLayout.java

@@ -1,611 +0,0 @@
-package cn.minbb.producttester.controls;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Rect;
-import android.graphics.Shader.TileMode;
-import android.os.Build;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-import cn.minbb.producttester.R;
-
-public class BaseFoldingLayout extends ViewGroup {
-
-    public static enum Orientation {
-        VERTICAL, HORIZONTAL
-    }
-
-    private final String FOLDING_VIEW_EXCEPTION_MESSAGE = "Folding Layout can only 1 child at most";
-
-    private final float SHADING_ALPHA = 0.8f;
-    private final float SHADING_FACTOR = 0.5f;
-    private final int DEPTH_CONSTANT = 1500;
-    private final int NUM_OF_POLY_POINTS = 8;
-
-    private Rect[] mFoldRectArray;
-
-    private Matrix[] mMatrix;
-
-    protected Orientation mOrientation = Orientation.VERTICAL;
-
-    protected float mAnchorFactor = 0;
-    private float mFoldFactor = 0;
-
-    private int mNumberOfFolds = 2;
-
-    private boolean mIsHorizontal = true;
-
-    private int mOriginalWidth = 0;
-    private int mOriginalHeight = 0;
-
-    private float mFoldMaxWidth = 0;
-    private float mFoldMaxHeight = 0;
-    private float mFoldDrawWidth = 0;
-    private float mFoldDrawHeight = 0;
-
-    private boolean mIsFoldPrepared = false;
-    private boolean mShouldDraw = true;
-
-    private Paint mSolidShadow;
-    private Paint mGradientShadow;
-    private LinearGradient mShadowLinearGradient;
-    private Matrix mShadowGradientMatrix;
-
-    private float[] mSrc;
-    private float[] mDst;
-
-    private OnFoldListener mFoldListener;
-
-    private float mPreviousFoldFactor = 0;
-
-    private Bitmap mFullBitmap;
-    private Rect mDstRect;
-
-    public BaseFoldingLayout(Context context) {
-        super(context);
-    }
-
-    public BaseFoldingLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init(context, attrs);
-    }
-
-    public BaseFoldingLayout(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        init(context, attrs);
-    }
-
-    public void init(Context context, AttributeSet attrs) {
-        // now style everything!
-        TypedArray ta = context.obtainStyledAttributes(attrs,
-                R.styleable.FoldingMenu);
-        int mFoldNumber = ta.getInt(R.styleable.FoldingMenu_foldNumber,
-                mNumberOfFolds);
-        if (mFoldNumber > 0 && mFoldNumber < 7) {
-            mNumberOfFolds = mFoldNumber;
-        } else {
-            mNumberOfFolds = 2;
-        }
-        ta.recycle();
-    }
-
-    @Override
-    protected boolean addViewInLayout(View child, int index,
-                                      LayoutParams params, boolean preventRequestLayout) {
-        throwCustomException(getChildCount());
-        boolean returnValue = super.addViewInLayout(child, index, params,
-                preventRequestLayout);
-        return returnValue;
-    }
-
-    @Override
-    public void addView(View child, int index, LayoutParams params) {
-        throwCustomException(getChildCount());
-        super.addView(child, index, params);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        View child = getChildAt(0);
-        measureChild(child, widthMeasureSpec, heightMeasureSpec);
-        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        View child = getChildAt(0);
-        child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
-        updateFold();
-    }
-
-    /**
-     * The custom exception to be thrown so as to limit the number of views in
-     * this layout to at most one.
-     */
-    private class NumberOfFoldingLayoutChildrenException extends
-            RuntimeException {
-        /**
-         *
-         */
-        private static final long serialVersionUID = 1L;
-
-        public NumberOfFoldingLayoutChildrenException(String message) {
-            super(message);
-        }
-    }
-
-    /**
-     * Throws an exception if the number of views added to this layout exceeds
-     * one.
-     */
-    private void throwCustomException(int numOfChildViews) {
-        if (numOfChildViews == 1) {
-            throw new NumberOfFoldingLayoutChildrenException(
-                    FOLDING_VIEW_EXCEPTION_MESSAGE);
-        }
-    }
-
-    public void setFoldListener(OnFoldListener foldListener) {
-        mFoldListener = foldListener;
-    }
-
-    /**
-     * Sets the fold factor of the folding view and updates all the
-     * corresponding matrices and values to account for the new fold factor.
-     * Once that is complete, it redraws itself with the new fold.
-     */
-    public void setFoldFactor(float foldFactor) {
-        if (foldFactor != mFoldFactor) {
-            mFoldFactor = foldFactor;
-            calculateMatrices();
-            invalidate();
-        }
-    }
-
-
-    public void setOrientation(Orientation orientation) {
-        if (orientation != mOrientation) {
-            mOrientation = orientation;
-            updateFold();
-        }
-    }
-
-    public void setAnchorFactor(float anchorFactor) {
-        if (anchorFactor != mAnchorFactor) {
-            mAnchorFactor = anchorFactor;
-            updateFold();
-        }
-    }
-
-    public void setNumberOfFolds(int numberOfFolds) {
-        if (numberOfFolds != mNumberOfFolds) {
-            mNumberOfFolds = numberOfFolds;
-            updateFold();
-        }
-    }
-
-    public float getAnchorFactor() {
-        return mAnchorFactor;
-    }
-
-    public Orientation getOrientation() {
-        return mOrientation;
-    }
-
-    public float getFoldFactor() {
-        return mFoldFactor;
-    }
-
-    public int getNumberOfFolds() {
-        return mNumberOfFolds;
-    }
-
-    private void updateFold() {
-        prepareFold(mOrientation, mAnchorFactor, mNumberOfFolds);
-        calculateMatrices();
-        invalidate();
-    }
-
-    /**
-     * This method is called in order to update the fold's orientation, anchor
-     * point and number of folds. This creates the necessary setup in order to
-     * prepare the layout for a fold with the specified parameters. Some of the
-     * dimensions required for the folding transformation are also acquired
-     * here.
-     * <p>
-     * After this method is called, it will be in a completely unfolded state by
-     * default.
-     */
-    private void prepareFold(Orientation orientation, float anchorFactor,
-                             int numberOfFolds) {
-
-        mSrc = new float[NUM_OF_POLY_POINTS];
-        mDst = new float[NUM_OF_POLY_POINTS];
-
-        mDstRect = new Rect();
-
-        mFoldFactor = 0;
-        mPreviousFoldFactor = 0;
-
-        mIsFoldPrepared = false;
-
-        mSolidShadow = new Paint();
-        mGradientShadow = new Paint();
-
-        mOrientation = orientation;
-        mIsHorizontal = (orientation == Orientation.HORIZONTAL);
-
-        if (mIsHorizontal) {
-            mShadowLinearGradient = new LinearGradient(0, 0, SHADING_FACTOR, 0,
-                    Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);
-        } else {
-            mShadowLinearGradient = new LinearGradient(0, 0, 0, SHADING_FACTOR,
-                    Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);
-        }
-
-        mGradientShadow.setStyle(Style.FILL);
-        mGradientShadow.setShader(mShadowLinearGradient);
-        mShadowGradientMatrix = new Matrix();
-
-        mAnchorFactor = anchorFactor;
-        mNumberOfFolds = numberOfFolds;
-
-        mOriginalWidth = getMeasuredWidth();
-        mOriginalHeight = getMeasuredHeight();
-
-        mFoldRectArray = new Rect[mNumberOfFolds];
-        mMatrix = new Matrix[mNumberOfFolds];
-
-        for (int x = 0; x < mNumberOfFolds; x++) {
-            mMatrix[x] = new Matrix();
-        }
-
-        int h = mOriginalHeight;
-        int w = mOriginalWidth;
-
-        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2 && h != 0 && w != 0) {
-            mFullBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(mFullBitmap);
-            getChildAt(0).draw(canvas);
-        }
-
-        int delta = Math.round(mIsHorizontal ? ((float) w)
-                / ((float) mNumberOfFolds) : ((float) h)
-                / ((float) mNumberOfFolds));
-
-        /*
-         * Loops through the number of folds and segments the full layout into a
-         * number of smaller equal components. If the number of folds is odd,
-         * then one of the components will be smaller than all the rest. Note
-         * that deltap below handles the calculation for an odd number of folds.
-         */
-        for (int x = 0; x < mNumberOfFolds; x++) {
-            if (mIsHorizontal) {
-                int deltap = (x + 1) * delta > w ? w - x * delta : delta;
-                mFoldRectArray[x] = new Rect(x * delta, 0, x * delta + deltap,
-                        h);
-            } else {
-                int deltap = (x + 1) * delta > h ? h - x * delta : delta;
-                mFoldRectArray[x] = new Rect(0, x * delta, w, x * delta
-                        + deltap);
-            }
-        }
-
-        if (mIsHorizontal) {
-            mFoldMaxHeight = h;
-            mFoldMaxWidth = delta;
-        } else {
-            mFoldMaxHeight = delta;
-            mFoldMaxWidth = w;
-        }
-
-        mIsFoldPrepared = true;
-    }
-
-    /*
-     * Calculates the transformation matrices used to draw each of the separate
-     * folding segments from this view.
-     */
-    private void calculateMatrices() {
-
-        mShouldDraw = true;
-
-        if (!mIsFoldPrepared) {
-            return;
-        }
-
-        /**
-         * If the fold factor is 1 than the folding view should not be seen and
-         * the canvas can be left completely empty.
-         */
-        if (mFoldFactor == 1) {
-            mShouldDraw = false;
-            return;
-        }
-
-//		if (mFoldFactor == 0 && mPreviousFoldFactor > 0
-//				&& mFoldListener != null) {
-//
-//			mFoldListener.onEndFold(mFoldFactor);
-//		}else if (mPreviousFoldFactor == 0 && mFoldFactor > 0
-//				&& mFoldListener != null) {
-//
-//			mFoldListener.onStartFold(mFoldFactor);
-//		} else if(mFoldListener != null) {
-//		    mFoldListener.onFoldingState(mFoldFactor);
-//		}
-
-        if (mFoldFactor > 0.9f && mFoldFactor > mPreviousFoldFactor
-                && mFoldListener != null) {
-
-            mFoldListener.onEndFold(mFoldFactor);
-        } else if (mFoldFactor < 0.1f && mFoldFactor < mPreviousFoldFactor
-                && mFoldListener != null) {
-
-            mFoldListener.onStartFold(mFoldFactor);
-        } else if (mFoldListener != null) {
-
-            mFoldListener.onFoldingState(mFoldFactor, mFoldDrawHeight);
-        }
-
-//		if(mFoldFactor == 0 && mFoldListener != null) {
-//            mFoldListener.onStartFold(mFoldFactor);
-//        } else if(mFoldFactor == 1 && mFoldListener != null) {
-//            mFoldListener.onEndFold(mFoldFactor);
-//        } else {
-//            mFoldListener.onFoldingState(mFoldFactor);
-//        }
-
-        mPreviousFoldFactor = mFoldFactor;
-
-        /*
-         * Reset all the transformation matrices back to identity before
-         * computing the new transformation
-         */
-        for (int x = 0; x < mNumberOfFolds; x++) {
-            mMatrix[x].reset();
-        }
-
-        float cTranslationFactor = 1 - mFoldFactor;
-
-        float translatedDistance = mIsHorizontal ? mOriginalWidth
-                * cTranslationFactor : mOriginalHeight * cTranslationFactor;
-
-        float translatedDistancePerFold = Math.round(translatedDistance
-                / mNumberOfFolds);
-
-        /*
-         * For an odd number of folds, the rounding error may cause the
-         * translatedDistancePerFold to be grater than the max fold width or
-         * height.
-         */
-        mFoldDrawWidth = mFoldMaxWidth < translatedDistancePerFold ? translatedDistancePerFold
-                : mFoldMaxWidth;
-        mFoldDrawHeight = mFoldMaxHeight < translatedDistancePerFold ? translatedDistancePerFold
-                : mFoldMaxHeight;
-
-        float translatedDistanceFoldSquared = translatedDistancePerFold
-                * translatedDistancePerFold;
-
-        /*
-         * Calculate the depth of the fold into the screen using pythagorean
-         * theorem.
-         */
-        float depth = mIsHorizontal ? (float) Math
-                .sqrt((double) (mFoldDrawWidth * mFoldDrawWidth - translatedDistanceFoldSquared))
-                : (float) Math
-                .sqrt((double) (mFoldDrawHeight * mFoldDrawHeight - translatedDistanceFoldSquared));
-
-        /*
-         * The size of some object is always inversely proportional to the
-         * distance it is away from the viewpoint. The constant can be varied to
-         * to affect the amount of perspective.
-         */
-        float scaleFactor = DEPTH_CONSTANT / (DEPTH_CONSTANT + depth);
-
-        float scaledWidth, scaledHeight, bottomScaledPoint, topScaledPoint, rightScaledPoint, leftScaledPoint;
-
-        if (mIsHorizontal) {
-            scaledWidth = mFoldDrawWidth * cTranslationFactor;
-            scaledHeight = mFoldDrawHeight * scaleFactor;
-        } else {
-            scaledWidth = mFoldDrawWidth * scaleFactor;
-            scaledHeight = mFoldDrawHeight * cTranslationFactor;
-        }
-
-        topScaledPoint = (mFoldDrawHeight - scaledHeight) / 2.0f;
-        bottomScaledPoint = topScaledPoint + scaledHeight;
-
-        leftScaledPoint = (mFoldDrawWidth - scaledWidth) / 2.0f;
-        rightScaledPoint = leftScaledPoint + scaledWidth;
-
-        float anchorPoint = mIsHorizontal ? mAnchorFactor * mOriginalWidth
-                : mAnchorFactor * mOriginalHeight;
-
-        /* The fold along which the anchor point is located. */
-        float midFold = mIsHorizontal ? (anchorPoint / mFoldDrawWidth)
-                : anchorPoint / mFoldDrawHeight;
-
-        mSrc[0] = 0;
-        mSrc[1] = 0;
-        mSrc[2] = 0;
-        mSrc[3] = mFoldDrawHeight;
-        mSrc[4] = mFoldDrawWidth;
-        mSrc[5] = 0;
-        mSrc[6] = mFoldDrawWidth;
-        mSrc[7] = mFoldDrawHeight;
-
-        /*
-         * Computes the transformation matrix for each fold using the values
-         * calculated above.
-         */
-        for (int x = 0; x < mNumberOfFolds; x++) {
-
-            boolean isEven = (x % 2 == 0);
-
-            if (mIsHorizontal) {
-                mDst[0] = (anchorPoint > x * mFoldDrawWidth) ? anchorPoint
-                        + (x - midFold) * scaledWidth : anchorPoint
-                        - (midFold - x) * scaledWidth;
-                mDst[1] = isEven ? 0 : topScaledPoint;
-                mDst[2] = mDst[0];
-                mDst[3] = isEven ? mFoldDrawHeight : bottomScaledPoint;
-                mDst[4] = (anchorPoint > (x + 1) * mFoldDrawWidth) ? anchorPoint
-                        + (x + 1 - midFold) * scaledWidth
-                        : anchorPoint - (midFold - x - 1) * scaledWidth;
-                mDst[5] = isEven ? topScaledPoint : 0;
-                mDst[6] = mDst[4];
-                mDst[7] = isEven ? bottomScaledPoint : mFoldDrawHeight;
-
-            } else {
-                mDst[0] = isEven ? 0 : leftScaledPoint;
-                mDst[1] = (anchorPoint > x * mFoldDrawHeight) ? anchorPoint
-                        + (x - midFold) * scaledHeight : anchorPoint
-                        - (midFold - x) * scaledHeight;
-                mDst[2] = isEven ? leftScaledPoint : 0;
-                mDst[3] = (anchorPoint > (x + 1) * mFoldDrawHeight) ? anchorPoint
-                        + (x + 1 - midFold) * scaledHeight
-                        : anchorPoint - (midFold - x - 1) * scaledHeight;
-                mDst[4] = isEven ? mFoldDrawWidth : rightScaledPoint;
-                mDst[5] = mDst[1];
-                mDst[6] = isEven ? rightScaledPoint : mFoldDrawWidth;
-                mDst[7] = mDst[3];
-            }
-
-            /*
-             * Pixel fractions are present for odd number of folds which need to
-             * be rounded off here.
-             */
-            for (int y = 0; y < 8; y++) {
-                mDst[y] = Math.round(mDst[y]);
-            }
-
-            /*
-             * If it so happens that any of the folds have reached a point where
-             * the width or height of that fold is 0, then nothing needs to be
-             * drawn onto the canvas because the view is essentially completely
-             * folded.
-             */
-            if (mIsHorizontal) {
-                if (mDst[4] <= mDst[0] || mDst[6] <= mDst[2]) {
-                    mShouldDraw = false;
-                    return;
-                }
-            } else {
-                if (mDst[3] <= mDst[1] || mDst[7] <= mDst[5]) {
-                    mShouldDraw = false;
-                    return;
-                }
-            }
-
-            /* Sets the shadow and bitmap transformation matrices. */
-            mMatrix[x].setPolyToPoly(mSrc, 0, mDst, 0, NUM_OF_POLY_POINTS / 2);
-        }
-        /*
-         * The shadows on the folds are split into two parts: Solid shadows and
-         * gradients. Every other fold has a solid shadow which overlays the
-         * whole fold. Similarly, the folds in between these alternating folds
-         * also have an overlaying shadow. However, it is a gradient that takes
-         * up part of the fold as opposed to a solid shadow overlaying the whole
-         * fold.
-         */
-
-        /* Solid shadow paint object. */
-        int alpha = (int) (mFoldFactor * 255 * SHADING_ALPHA);
-
-        mSolidShadow.setColor(Color.argb(alpha, 0, 0, 0));
-
-        if (mIsHorizontal) {
-            mShadowGradientMatrix.setScale(mFoldDrawWidth, 1);
-            mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
-        } else {
-            mShadowGradientMatrix.setScale(1, mFoldDrawHeight);
-            mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
-        }
-
-        mGradientShadow.setAlpha(alpha);
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        /**
-         * If prepareFold has not been called or if preparation has not
-         * completed yet, then no custom drawing will take place so only need to
-         * invoke super's onDraw and return.
-         */
-        if (!mIsFoldPrepared || mFoldFactor == 0) {
-            super.dispatchDraw(canvas);
-            return;
-        }
-
-        if (!mShouldDraw) {
-            return;
-        }
-
-        Rect src;
-        /*
-         * Draws the bitmaps and shadows on the canvas with the appropriate
-         * transformations.
-         */
-        for (int x = 0; x < mNumberOfFolds; x++) {
-
-            src = mFoldRectArray[x];
-            /* The canvas is saved and restored for every individual fold */
-            canvas.save();
-
-            /*
-             * Concatenates the canvas with the transformation matrix for the
-             * the segment of the view corresponding to the actual image being
-             * displayed.
-             */
-            canvas.concat(mMatrix[x]);
-            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2) {
-                mDstRect.set(0, 0, src.width(), src.height());
-                canvas.drawBitmap(mFullBitmap, src, mDstRect, null);
-            } else {
-                /*
-                 * The same transformation matrix is used for both the shadow
-                 * and the image segment. The canvas is clipped to account for
-                 * the size of each fold and is translated so they are drawn in
-                 * the right place. The shadow is then drawn on top of the
-                 * different folds using the sametransformation matrix.
-                 */
-                canvas.clipRect(0, 0, src.right - src.left, src.bottom
-                        - src.top);
-
-                if (mIsHorizontal) {
-                    canvas.translate(-src.left, 0);
-                } else {
-                    canvas.translate(0, -src.top);
-                }
-
-                super.dispatchDraw(canvas);
-
-                if (mIsHorizontal) {
-                    canvas.translate(src.left, 0);
-                } else {
-                    canvas.translate(0, src.top);
-                }
-            }
-            /* Draws the shadows corresponding to this specific fold. */
-            if (x % 2 == 0) {
-                canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight,
-                        mSolidShadow);
-            } else {
-                canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight,
-                        mGradientShadow);
-            }
-
-            canvas.restore();
-        }
-    }
-}

+ 0 - 157
app/src/main/java/cn/minbb/producttester/controls/FoldingLayout.java

@@ -1,157 +0,0 @@
-package cn.minbb.producttester.controls;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-
-public class FoldingLayout extends BaseFoldingLayout {
-
-    private final String FOLDING_VIEW_EXCEPTION_MESSAGE = "Folding Layout can only 1 child at most";
-
-    private GestureDetector mScrollGestureDetector;
-
-    FoldingLayout that = null;
-
-    private int mTranslation = 0;
-    private int mParentPositionY = -1;
-    private int mTouchSlop = -1;
-    private boolean mDidNotStartScroll = true;
-
-    public FoldingLayout(Context context) {
-        super(context);
-        init(context, null);
-        that = this;
-    }
-
-    public FoldingLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init(context, attrs);
-        that = this;
-    }
-
-    public FoldingLayout(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        init(context, attrs);
-        that = this;
-    }
-
-    public void init(Context context, AttributeSet attrs) {
-        mScrollGestureDetector = new GestureDetector(context, new ScrollGestureDetector());
-        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
-        setAnchorFactor(0);
-        super.init(context, attrs);
-    }
-
-    @Override
-    protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout) {
-        throwCustomException(getChildCount());
-        boolean returnValue = super.addViewInLayout(child, index, params, preventRequestLayout);
-        return returnValue;
-    }
-
-    /**
-     * The custom exception to be thrown so as to limit the number of views in
-     * this layout to at most one.
-     */
-    private class NumberOfFoldingLayoutChildrenException extends
-            RuntimeException {
-        /**
-         *
-         */
-        private static final long serialVersionUID = 1L;
-
-        public NumberOfFoldingLayoutChildrenException(String message) {
-            super(message);
-        }
-    }
-
-    /**
-     * Throws an exception if the number of views added to this layout exceeds one.
-     */
-    private void throwCustomException(int numOfChildViews) {
-        if (numOfChildViews == 1) {
-            throw new NumberOfFoldingLayoutChildrenException(FOLDING_VIEW_EXCEPTION_MESSAGE);
-        }
-    }
-
-    /**
-     * This class uses user touch events to fold and unfold the folding view.
-     */
-    private class ScrollGestureDetector extends GestureDetector.SimpleOnGestureListener {
-        @Override
-        public boolean onDown(MotionEvent e) {
-            mDidNotStartScroll = true;
-            return true;
-        }
-
-        /**
-         * All the logic here is used to determine by what factor the paper view
-         * should be folded in response to the user's touch events. The logic
-         * here uses vertical scrolling to fold a vertically oriented view and
-         * horizontal scrolling to fold a horizontally oriented fold. Depending
-         * on where the anchor point of the fold is, movements towards or away
-         * from the anchor point will either fold or unfold the paper
-         * respectively.
-         * <p>
-         * The translation logic here also accounts for the touch slop when a
-         * new user touch begins, but before a scroll event is first invoked.
-         */
-        @Override
-        public boolean onScroll(MotionEvent e1, MotionEvent e2,
-                                float distanceX, float distanceY) {
-            int touchSlop = 0;
-            float factor;
-            if (mOrientation == Orientation.VERTICAL) {
-                factor = Math.abs((float) (mTranslation) / (float) (that.getHeight()));
-                if (e2.getY() - mParentPositionY <= that.getHeight() && e2.getY() - mParentPositionY >= 0) {
-                    if ((e2.getY() - mParentPositionY) > that.getHeight() * getAnchorFactor()) {
-                        mTranslation -= (int) distanceY;
-                        touchSlop = distanceY < 0 ? -mTouchSlop : mTouchSlop;
-                    } else {
-                        mTranslation += (int) distanceY;
-                        touchSlop = distanceY < 0 ? mTouchSlop : -mTouchSlop;
-                    }
-                    mTranslation = mDidNotStartScroll ? mTranslation + touchSlop : mTranslation;
-
-                    if (mTranslation < -that.getHeight()) {
-                        mTranslation = -that.getHeight();
-                    }
-                }
-            } else {
-                factor = Math.abs(((float) mTranslation) / ((float) that.getWidth()));
-                if (e2.getRawX() > that.getWidth() * getAnchorFactor()) {
-                    mTranslation -= (int) distanceX;
-                    touchSlop = distanceX < 0 ? -mTouchSlop : mTouchSlop;
-                } else {
-                    mTranslation += (int) distanceX;
-                    touchSlop = distanceX < 0 ? mTouchSlop : -mTouchSlop;
-                }
-                mTranslation = mDidNotStartScroll ? mTranslation + touchSlop : mTranslation;
-
-                if (mTranslation < -that.getWidth()) {
-                    mTranslation = -that.getWidth();
-                }
-            }
-
-            mDidNotStartScroll = false;
-
-            if (mTranslation > 0) {
-                mTranslation = 0;
-            }
-
-            that.setFoldFactor(factor);
-
-            return true;
-        }
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent me) {
-        return mScrollGestureDetector.onTouchEvent(me);
-    }
-
-}

+ 0 - 9
app/src/main/java/cn/minbb/producttester/controls/OnFoldListener.java

@@ -1,9 +0,0 @@
-package cn.minbb.producttester.controls;
-
-public interface OnFoldListener {
-    public void onStartFold(float foldFactor);
-
-    public void onFoldingState(float foldFactor, float foldDrawHeight);
-
-    public void onEndFold(float foldFactor);
-}

+ 3 - 0
app/src/main/java/cn/minbb/producttester/ctrl/App.java

@@ -41,6 +41,9 @@ public class App extends Application {
     @Getter
     @Setter
     private BluetoothAdapter bluetoothAdapter;
+    @Getter
+    @Setter
+    private BluetoothDevice bluetoothDevice = null;
 
     public App() {
     }

+ 129 - 169
app/src/main/java/cn/minbb/producttester/views/ScanDeviceActivity.java

@@ -1,8 +1,5 @@
 package cn.minbb.producttester.views;
 
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.annotation.SuppressLint;
 import android.app.ProgressDialog;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
@@ -17,66 +14,42 @@ import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.annotation.NonNull;
+import android.support.v7.app.AlertDialog;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.app.AppCompatDelegate;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.animation.AccelerateInterpolator;
 import android.widget.AdapterView;
-import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.Toast;
 
-import com.joanzapata.iconify.widget.IconTextView;
-
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
-import java.util.Timer;
-import java.util.TimerTask;
 import java.util.UUID;
+import java.util.function.Consumer;
 
 import butterknife.BindView;
 import butterknife.ButterKnife;
-import butterknife.OnClick;
 import cn.minbb.producttester.R;
 import cn.minbb.producttester.adapter.DeviceListAdapter;
-import cn.minbb.producttester.controls.FoldingLayout;
-import cn.minbb.producttester.controls.OnFoldListener;
 import cn.minbb.producttester.ctrl.App;
 
 public class ScanDeviceActivity extends AppCompatActivity {
 
-    @BindView(R.id.matchListLayout)
-    LinearLayout matchListLayout;
-    @BindView(R.id.searchListLayout)
-    LinearLayout searchListLayout;
-    @BindView(R.id.matchListArrow)
-    IconTextView matchListArrow;
-    @BindView(R.id.searchListArrow)
-    IconTextView searchListArrow;
-    @BindView(R.id.matchListFolding)
-    FoldingLayout matchListFolding;
-    @BindView(R.id.searchListFolding)
-    FoldingLayout searchListFolding;
-    @BindView(R.id.matchList)
-    ListView matchList;
-    @BindView(R.id.searchList)
-    ListView searchList;
-    @BindView(R.id.bottomLayout)
-    View bottomLayout;
+    @BindView(R.id.deviceList)
+    ListView deviceList;
 
     private ProgressDialog dialog;
 
     private BluetoothAdapter adapter = App.getApp().getBluetoothAdapter();
-    List<DeviceListAdapter.ItemBean> matchItemBeanList = new ArrayList<>();
-    List<DeviceListAdapter.ItemBean> searchItemBeanList = new ArrayList<>();
-    private DeviceListAdapter matchDeviceListAdapter;
-    private DeviceListAdapter searchDeviceListAdapter;
+    private List<DeviceListAdapter.ItemBean> deviceItemBeanList = new ArrayList<>();
+    private DeviceListAdapter deviceListAdapter;
+    private BluetoothDevice selectDevice;
+    private int selectIndex;
 
     static {
         AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
@@ -111,12 +84,10 @@ public class ScanDeviceActivity extends AppCompatActivity {
             }
             Set<BluetoothDevice> devices = adapter.getBondedDevices();
             for (BluetoothDevice device : devices) {
-                matchItemBeanList.add(new DeviceListAdapter.ItemBean(device));
+                deviceItemBeanList.add(new DeviceListAdapter.ItemBean(device));
             }
-            matchDeviceListAdapter = new DeviceListAdapter(this, matchItemBeanList);
-            matchList.setAdapter(matchDeviceListAdapter);
-            searchDeviceListAdapter = new DeviceListAdapter(this, searchItemBeanList);
-            searchList.setAdapter(searchDeviceListAdapter);
+            deviceListAdapter = new DeviceListAdapter(this, deviceItemBeanList);
+            deviceList.setAdapter(deviceListAdapter);
         }
 
         initView();
@@ -130,30 +101,46 @@ public class ScanDeviceActivity extends AppCompatActivity {
         this.unregisterReceiver(receiver);
     }
 
+    public static void start(Context context) {
+        Intent starter = new Intent(context, ScanDeviceActivity.class);
+        context.startActivity(starter);
+    }
+
     private void initView() {
         App.setupActionBar(this);
     }
 
     private void setListener() {
-        matchList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+        deviceList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
-                // 尝试连接
-            }
-        });
-        searchList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-            @Override
-            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                // 尝试配对
-                try {
-                    Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
-                    createBondMethod.invoke(searchItemBeanList.get(position).device);
-                } catch (NoSuchMethodException e) {
-                    e.printStackTrace();
-                } catch (IllegalAccessException e) {
-                    e.printStackTrace();
-                } catch (InvocationTargetException e) {
-                    e.printStackTrace();
+                selectIndex = i;
+                selectDevice = deviceItemBeanList.get(i).device;
+                switch (selectDevice.getBondState()) {
+                    case BluetoothDevice.BOND_NONE:
+                        // 未配对 - 尝试配对
+                        try {
+                            Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
+                            createBondMethod.invoke(selectDevice);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                        break;
+                    case BluetoothDevice.BOND_BONDING:
+                        // 配对中
+                        break;
+                    case BluetoothDevice.BOND_BONDED:
+                        // 已配对 - 尝试连接
+                        // 固定的 UUID
+                        String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
+                        UUID uuid = UUID.fromString(SPP_UUID);
+                        try {
+                            BluetoothSocket socket = selectDevice.createRfcommSocketToServiceRecord(uuid);
+                            socket.connect();
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        break;
                 }
             }
         });
@@ -168,108 +155,53 @@ public class ScanDeviceActivity extends AppCompatActivity {
         }
     }
 
-    public static void start(Context context) {
-        Intent starter = new Intent(context, ScanDeviceActivity.class);
-        context.startActivity(starter);
-    }
-
-    private void showProgress(boolean show) {
+    private void showSearchDeviceProgress(boolean show) {
         if (dialog == null) {
             dialog = new ProgressDialog(this);
             dialog.setTitle("蓝牙串口");
             dialog.setMessage("搜索设备中······");
             dialog.setCancelable(false);
-            dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialogInterface, int i) {
-                    adapter.cancelDiscovery();
-                    dialog.dismiss();
+            dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", (dialogInterface, i) -> {
+                adapter.cancelDiscovery();
+                dialog.dismiss();
+            });
+            dialog.setOnDismissListener(dialog -> {
+                int count = 0;
+                for (DeviceListAdapter.ItemBean itemBean : deviceItemBeanList) {
+                    if (itemBean.device.getBondState() == BluetoothDevice.BOND_NONE) {
+                        count++;
+                    }
                 }
+                Toast.makeText(ScanDeviceActivity.this, "查找到 " + count + " 个蓝牙设备", Toast.LENGTH_SHORT).show();
             });
         }
         if (show) {
             dialog.show();
         } else {
             dialog.dismiss();
+            dialog = null;
         }
     }
 
-    private void handleAnimation(final View bar, final FoldingLayout foldingLayout, View parent, final View nextParent) {
-        foldingLayout.setFoldListener(new OnFoldListener() {
-            @Override
-            public void onStartFold(float foldFactor) {
-                bar.setClickable(true);
-                matchListArrow.setText("{fa-chevron-up}");
-                resetMarginToTop(foldingLayout, foldFactor, nextParent);
-            }
-
-            @Override
-            public void onFoldingState(float foldFactor, float foldDrawHeight) {
-                bar.setClickable(false);
-                resetMarginToTop(foldingLayout, foldFactor, nextParent);
-            }
-
-            @Override
-            public void onEndFold(float foldFactor) {
-                bar.setClickable(true);
-                matchListArrow.setText("{fa-chevron-up}");
-                resetMarginToTop(foldingLayout, foldFactor, nextParent);
-            }
-        });
-        animateFold(foldingLayout, 500);
-    }
-
-    private void resetMarginToTop(View view, float foldFactor, View nextParent) {
-        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) nextParent.getLayoutParams();
-        lp.topMargin = (int) (-view.getMeasuredHeight() * foldFactor) + dp2px(ScanDeviceActivity.this, 10);
-        nextParent.setLayoutParams(lp);
-    }
-
-    private void setMarginToTop(float foldFactor, View nextParent) {
-        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) nextParent.getLayoutParams();
-        lp.topMargin = (int) (-dp2px(ScanDeviceActivity.this, 135) * foldFactor) + dp2px(ScanDeviceActivity.this, 10);
-        nextParent.setLayoutParams(lp);
-    }
-
-    @SuppressLint("NewApi")
-    public void animateFold(FoldingLayout foldLayout, int duration) {
-        float foldFactor = foldLayout.getFoldFactor();
-        ObjectAnimator animator = ObjectAnimator.ofFloat(foldLayout, "foldFactor", foldFactor, foldFactor > 0 ? 0 : 1);
-        animator.setRepeatMode(ValueAnimator.REVERSE);
-        animator.setRepeatCount(0);
-        animator.setDuration(duration);
-        animator.setInterpolator(new AccelerateInterpolator());
-        animator.start();
-    }
-
-    public static int dp2px(Context context, float dpValue) {
-        float density = context.getResources().getDisplayMetrics().density;
-        return (int) (dpValue * density + 0.5f);
-    }
-
-    private void connect(BluetoothDevice device) throws IOException {
-        // 固定的 UUID
-        String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
-        UUID uuid = UUID.fromString(SPP_UUID);
-        BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid);
-        socket.connect();
-    }
-
-    @OnClick({R.id.matchListToggle, R.id.searchListToggle})
-    public void onViewClicked(View view) {
-        switch (view.getId()) {
-            case R.id.matchListToggle:
-                handleAnimation(view, matchListFolding, matchListLayout, searchListLayout);
-                break;
-            case R.id.searchListToggle:
-                handleAnimation(view, searchListFolding, searchListLayout, bottomLayout);
-                break;
+    private void showMatchDeviceProgress(boolean show) {
+        if (dialog == null) {
+            dialog = new ProgressDialog(this);
+            dialog.setTitle("配对");
+            dialog.setMessage("设备配对中······");
+            dialog.setCancelable(false);
+        }
+        if (show) {
+            dialog.show();
+        } else {
+            dialog.dismiss();
+            dialog = null;
         }
     }
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
-        menu.add(0, 0, 0, "搜索设备").setIcon(R.drawable.ic_search_white_24dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+        menu.add(0, 0, 0, "提示").setIcon(R.drawable.ic_info_outline_white_24dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+        menu.add(0, 1, 0, "搜索设备").setIcon(R.drawable.ic_search_white_24dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
         return super.onCreateOptionsMenu(menu);
     }
 
@@ -280,8 +212,23 @@ public class ScanDeviceActivity extends AppCompatActivity {
                 ScanDeviceActivity.this.finish();
                 break;
             case 0:
-                showProgress(true);
-                matchItemBeanList.clear();
+                AlertDialog.Builder builder = new AlertDialog.Builder(ScanDeviceActivity.this);
+                builder.setIcon(R.drawable.ic_info_outline_black_24dp);
+                builder.setTitle("提示");
+                builder.setMessage("点击已配对的设备进行连接\n点击搜索到的设备进行配对");
+                builder.setPositiveButton("好的", null);
+                builder.create().show();
+                break;
+            case 1:
+                showSearchDeviceProgress(true);
+                List<DeviceListAdapter.ItemBean> unboundItemBeanList = new ArrayList<>();
+                for (DeviceListAdapter.ItemBean itemBean : deviceItemBeanList) {
+                    if (itemBean.device.getBondState() == BluetoothDevice.BOND_NONE) {
+                        unboundItemBeanList.add(itemBean);
+                    }
+                }
+                deviceItemBeanList.removeAll(unboundItemBeanList);
+                deviceListAdapter.notifyDataSetChanged();
                 // 打开蓝牙
                 if (!adapter.isEnabled()) {
                     Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
@@ -297,7 +244,7 @@ public class ScanDeviceActivity extends AppCompatActivity {
                 // Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                 // startActivityForResult(intent, 1);
                 new Handler().postDelayed(() -> runOnUiThread(() -> {
-                    showProgress(false);
+                    showSearchDeviceProgress(false);
                     adapter.cancelDiscovery();
                 }), 20000);
                 break;
@@ -335,7 +282,9 @@ public class ScanDeviceActivity extends AppCompatActivity {
         switch (requestCode) {
             case 1:
                 if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-                    System.out.println("权限请求成功");
+                    Toast.makeText(ScanDeviceActivity.this, "授权成功", Toast.LENGTH_SHORT).show();
+                } else {
+                    Toast.makeText(ScanDeviceActivity.this, "未获得授权,将无法进行扫描", Toast.LENGTH_SHORT).show();
                 }
                 break;
             default:
@@ -350,31 +299,33 @@ public class ScanDeviceActivity extends AppCompatActivity {
                 // 获取查找到的蓝牙设备
                 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
 
-                matchItemBeanList.add(new DeviceListAdapter.ItemBean(device));
-                searchDeviceListAdapter.notifyDataSetChanged();
+                if (!deviceItemBeanList.contains(new DeviceListAdapter.ItemBean(device)) && device.getName() != null && device.getAddress() != null) {
+                    deviceItemBeanList.add(new DeviceListAdapter.ItemBean(device));
+                    deviceListAdapter.notifyDataSetChanged();
+                }
 
                 // 如果查找到的设备符合要连接的设备,处理
-                if (device.getName().equalsIgnoreCase(device.getName())) {
-                    // 搜索蓝牙设备的过程占用资源比较多,一旦找到需要连接的设备后需要及时关闭搜索
-                    App.getApp().getBluetoothAdapter().cancelDiscovery();
-                    // 获取蓝牙设备的连接状态
-                    switch (device.getBondState()) {
-                        // 未配对
-                        case BluetoothDevice.BOND_NONE:
-                            // 配对
-                            try {
-                                Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
-                                createBondMethod.invoke(device);
-                            } catch (Exception e) {
-                                e.printStackTrace();
-                            }
-                            break;
-                        // 已配对
-                        case BluetoothDevice.BOND_BONDED:
-                            // 连接
-                            break;
-                    }
-                }
+//                if (device.getName().equalsIgnoreCase(device.getName())) {
+//                    // 搜索蓝牙设备的过程占用资源比较多,一旦找到需要连接的设备后需要及时关闭搜索
+//                    App.getApp().getBluetoothAdapter().cancelDiscovery();
+//                    // 获取蓝牙设备的连接状态
+//                    switch (device.getBondState()) {
+//                        // 未配对
+//                        case BluetoothDevice.BOND_NONE:
+//                            // 配对
+//                            try {
+//                                Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
+//                                createBondMethod.invoke(device);
+//                            } catch (Exception e) {
+//                                e.printStackTrace();
+//                            }
+//                            break;
+//                        // 已配对
+//                        case BluetoothDevice.BOND_BONDED:
+//                            // 连接
+//                            break;
+//                    }
+//                }
             } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                 // 状态改变的广播
                 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
@@ -382,12 +333,21 @@ public class ScanDeviceActivity extends AppCompatActivity {
                     switch (device.getBondState()) {
                         case BluetoothDevice.BOND_NONE:
                             // 取消配对
+                            System.out.println("取消配对");
+                            showMatchDeviceProgress(false);
                             break;
                         case BluetoothDevice.BOND_BONDING:
                             // 正在配对
+                            System.out.println("正在配对");
+                            showMatchDeviceProgress(true);
                             break;
                         case BluetoothDevice.BOND_BONDED:
                             // 完成配对
+                            System.out.println("完成配对");
+                            showMatchDeviceProgress(false);
+                            deviceItemBeanList.set(selectIndex, new DeviceListAdapter.ItemBean(device));
+                            deviceListAdapter.notifyDataSetChanged();
+                            Toast.makeText(ScanDeviceActivity.this, "和设备 " + device.getName() + " 配对成功", Toast.LENGTH_SHORT).show();
                             break;
                     }
                 }
@@ -397,12 +357,12 @@ public class ScanDeviceActivity extends AppCompatActivity {
                         Toast.makeText(ScanDeviceActivity.this, "蓝牙已关闭", Toast.LENGTH_SHORT).show();
                         ScanDeviceActivity.this.finish();
                     } else {
-                        matchItemBeanList.clear();
+                        deviceItemBeanList.clear();
                         Set<BluetoothDevice> devices = adapter.getBondedDevices();
                         for (BluetoothDevice device : devices) {
-                            matchItemBeanList.add(new DeviceListAdapter.ItemBean(device));
+                            deviceItemBeanList.add(new DeviceListAdapter.ItemBean(device));
                         }
-                        matchDeviceListAdapter.notifyDataSetChanged();
+                        deviceListAdapter.notifyDataSetChanged();
                     }
                 }), 500);
             }

+ 9 - 0
app/src/main/res/drawable/ic_info_outline_black_24dp.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>

+ 5 - 0
app/src/main/res/drawable/ic_info_outline_white_24dp.xml

@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#FFFFFF"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>

+ 44 - 171
app/src/main/res/layout/activity_scan_device.xml

@@ -7,180 +7,53 @@
     android:orientation="vertical"
     tools:context=".views.ScanDeviceActivity">
 
-    <LinearLayout
-        android:id="@+id/matchListLayout"
+    <android.support.v7.widget.CardView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginLeft="8dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
-        android:layout_marginRight="8dp"
-        android:orientation="vertical">
-
-        <android.support.v7.widget.CardView
-            android:id="@+id/matchListToggle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:clickable="true"
-            android:focusable="true"
-            android:foreground="?android:attr/selectableItemBackground"
-            app:cardBackgroundColor="@android:color/white"
-            app:cardCornerRadius="5dp"
-            app:cardPreventCornerOverlap="true"
-            app:cardUseCompatPadding="true">
-
-            <android.support.constraint.ConstraintLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-                <com.joanzapata.iconify.widget.IconTextView
-                    android:id="@+id/matchListIcon"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginStart="12dp"
-                    android:layout_marginLeft="12dp"
-                    android:layout_marginTop="12dp"
-                    android:layout_marginBottom="12dp"
-                    android:text="{fa-link}"
-                    app:layout_constraintBottom_toBottomOf="parent"
-                    app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent" />
-
-                <TextView
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginStart="8dp"
-                    android:layout_marginLeft="8dp"
-                    android:layout_marginTop="12dp"
-                    android:layout_marginBottom="12dp"
-                    android:text="已配对"
-                    app:layout_constraintBottom_toBottomOf="parent"
-                    app:layout_constraintStart_toEndOf="@+id/matchListIcon"
-                    app:layout_constraintTop_toTopOf="parent" />
-
-                <com.joanzapata.iconify.widget.IconTextView
-                    android:id="@+id/matchListArrow"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="end"
-                    android:layout_marginTop="12dp"
-                    android:layout_marginEnd="12dp"
-                    android:layout_marginRight="12dp"
-                    android:layout_marginBottom="12dp"
-                    android:text="{fa-chevron-down}"
-                    app:layout_constraintBottom_toBottomOf="parent"
-                    app:layout_constraintEnd_toEndOf="parent"
-                    app:layout_constraintTop_toTopOf="parent" />
-
-            </android.support.constraint.ConstraintLayout>
-
-        </android.support.v7.widget.CardView>
-
-        <cn.minbb.producttester.controls.FoldingLayout
-            android:id="@+id/matchListFolding"
-            android:layout_width="match_parent"
-            android:layout_height="200dp"
-            android:tag="main">
-
-            <ListView
-                android:id="@+id/matchList"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-
-        </cn.minbb.producttester.controls.FoldingLayout>
-
-    </LinearLayout>
-
-    <LinearLayout
-        android:id="@+id/searchListLayout"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginLeft="8dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
-        android:layout_marginRight="8dp"
-        android:orientation="vertical">
-
-        <android.support.v7.widget.CardView
-            android:id="@+id/searchListToggle"
+        android:clickable="true"
+        android:focusable="true"
+        android:foreground="?android:attr/selectableItemBackground"
+        app:cardBackgroundColor="@android:color/white"
+        app:cardCornerRadius="5dp"
+        app:cardPreventCornerOverlap="true"
+        app:cardUseCompatPadding="true">
+
+        <android.support.constraint.ConstraintLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:clickable="true"
-            android:focusable="true"
-            android:foreground="?android:attr/selectableItemBackground"
-            app:cardBackgroundColor="@android:color/white"
-            app:cardCornerRadius="5dp"
-            app:cardPreventCornerOverlap="true"
-            app:cardUseCompatPadding="true">
-
-            <android.support.constraint.ConstraintLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-                <com.joanzapata.iconify.widget.IconTextView
-                    android:id="@+id/iconTextView2"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginStart="12dp"
-                    android:layout_marginLeft="12dp"
-                    android:layout_marginTop="12dp"
-                    android:layout_marginBottom="12dp"
-                    android:text="{fa-unlink}"
-                    app:layout_constraintBottom_toBottomOf="parent"
-                    app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent" />
-
-                <TextView
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginStart="8dp"
-                    android:layout_marginLeft="8dp"
-                    android:layout_marginTop="12dp"
-                    android:layout_marginBottom="12dp"
-                    android:text="搜索列表"
-                    app:layout_constraintBottom_toBottomOf="parent"
-                    app:layout_constraintStart_toEndOf="@+id/iconTextView2"
-                    app:layout_constraintTop_toTopOf="parent" />
-
-                <com.joanzapata.iconify.widget.IconTextView
-                    android:id="@+id/searchListArrow"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="end"
-                    android:layout_marginTop="12dp"
-                    android:layout_marginEnd="12dp"
-                    android:layout_marginRight="12dp"
-                    android:layout_marginBottom="12dp"
-                    android:text="{fa-chevron-down}"
-                    app:layout_constraintBottom_toBottomOf="parent"
-                    app:layout_constraintEnd_toEndOf="parent"
-                    app:layout_constraintTop_toTopOf="parent" />
-
-            </android.support.constraint.ConstraintLayout>
-
-        </android.support.v7.widget.CardView>
-
-        <cn.minbb.producttester.controls.FoldingLayout
-            android:id="@+id/searchListFolding"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:tag="main">
-
-            <ListView
-                android:id="@+id/searchList"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-
-        </cn.minbb.producttester.controls.FoldingLayout>
-
-    </LinearLayout>
-
-    <View
-        android:id="@+id/bottomLayout"
+            android:layout_height="wrap_content">
+
+            <com.joanzapata.iconify.widget.IconTextView
+                android:id="@+id/deviceListIcon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="12dp"
+                android:layout_marginLeft="12dp"
+                android:layout_marginTop="12dp"
+                android:layout_marginBottom="12dp"
+                android:text="{fa-tasks}"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginLeft="8dp"
+                android:layout_marginTop="12dp"
+                android:layout_marginBottom="12dp"
+                android:text="设备列表"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toEndOf="@+id/deviceListIcon"
+                app:layout_constraintTop_toTopOf="parent" />
+
+        </android.support.constraint.ConstraintLayout>
+
+    </android.support.v7.widget.CardView>
+
+    <ListView
+        android:id="@+id/deviceList"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp" />
+        android:layout_height="wrap_content" />
 
 </LinearLayout>

+ 27 - 3
app/src/main/res/layout/item_device_list.xml

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
@@ -14,7 +15,7 @@
         android:text="设备名称"
         android:textColor="@android:color/black"
         android:textSize="18sp"
-        android:textStyle="bold"
+        android:textStyle="normal"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent" />
 
@@ -23,9 +24,32 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginStart="8dp"
-        android:layout_marginLeft="8dp"
         android:layout_marginTop="4dp"
+        android:layout_marginBottom="4dp"
         android:text="设备地址"
+        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/deviceName" />
+        app:layout_constraintTop_toBottomOf="@+id/deviceName"
+        app:layout_constraintVertical_bias="0.0" />
+
+    <com.joanzapata.iconify.widget.IconTextView
+        android:id="@+id/deviceStatus"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:layout_marginEnd="8dp"
+        android:text="设备状态"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/deviceTip"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="8dp"
+        android:text="设备提示"
+        android:textSize="12sp"
+        android:textStyle="italic"
+        app:layout_constraintBottom_toBottomOf="@+id/deviceAddress"
+        app:layout_constraintEnd_toEndOf="parent" />
 </android.support.constraint.ConstraintLayout>

+ 0 - 4
app/src/main/res/values/attrs.xml

@@ -9,8 +9,4 @@
         <attr name="metaButtonBarButtonStyle" format="reference" />
     </declare-styleable>
 
-    <declare-styleable name="FoldingMenu">
-        <attr name="foldNumber" format="integer" />
-    </declare-styleable>
-
 </resources>