2015-01-03 09:14:46 y_f123 阅读数 1496

<html>
<head>
    <title>9宫格</title>
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0" />  
    <script type="text/javascript" src="
http://code.jquery.com/jquery-1.5.min.js"></script>
    <link rel="stylesheet" href="
http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.css" />
    <script type="text/javascript" src="
http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.js"></script
</head>
<body>
  <div data-role="page" id="homepage">
    <div data-role="header" data-position="fixed">
        <a href="#" data-role="button" data-theme="a" data-icon="back">返回</a>
        <h1>9宫格</h1>
        <a href="#" data-role="button" data-theme="a" data-icon="forward">前进</a>
    </div>
    <div data-role="content">
       <div class="ui-grid-b">
           <div class="ui-block-a">
               <a href="#" data-role="button" data-theme="a" data-icon="home" data-iconpos="top">首页</a>
           </div>
           <div class="ui-block-b">
               <a href="#" data-role="button" data-theme="a" data-icon="grid" data-iconpos="top">列表</a>
           </div>
           <div class="ui-block-c">
               <a href="#" data-role="button" data-theme="a" data-icon="star" data-iconpos="top">加星</a>
           </div>
           <div class="ui-block-a">
               <a href="#" data-role="button" data-theme="a" data-icon="info" data-iconpos="top">信息</a>
           </div>
           <div class="ui-block-b">
               <a href="#" data-role="button" data-theme="a" data-icon="search" data-iconpos="top">查找</a>
           </div>
           <div class="ui-block-c">
               <a href="#" data-role="button" data-theme="a" data-icon="gear" data-iconpos="top">设置</a>
           </div>
           <div class="ui-block-a">
               <a href="#" data-role="button" data-theme="a" data-icon="check" data-iconpos="top">已选</a>
           </div>
           <div class="ui-block-b">
               <a href="#" data-role="button" data-theme="a" data-icon="alert" data-iconpos="top">提示</a>
           </div>
           <div class="ui-block-c">
               <a href="#" data-role="button" data-theme="a" data-icon="plus" data-iconpos="top">添加</a>
           </div>
       </div>
    </div>    
  </div>
</body>
</html>

效果:

 

 


2015-10-10 15:04:02 qq909157370 阅读数 1207

9宫格图片可以指定缩放区域,任意png图片都可以,通常用来做聊天消息等的背景


安卓中可以使用google提供的工具制作 9.png图片,直接把 9.png图片作为背景就可以。

ios要通过代码实现



关键代码

 
    
    UIButton* but=[UIButton buttonWithType:UIButtonTypeCustom];
    but.frame=CGRectMake(20, 100, 150, 40);
    [but setTitle:@"hello world" forState:UIControlStateNormal];
    
    UIEdgeInsets ins;
    
    ins.left=20;
    ins.right=20;
    ins.top=0;
    ins.bottom=0;
    
    
    UIImage* img=[UIImage imageNamed:@"bg3"];
    img=[img resizableImageWithCapInsets:ins];
    
    [but setBackgroundImage:img forState:UIControlStateNormal];
    
    but.center=self.view.center;
    [self.view addSubview:but];

背景图片3 ,尺寸 42*40


效果图


2018-05-03 13:02:48 DeMonliuhui 阅读数 779

效果图

话不多说,上效果图。

这里写图片描述

9宫格图形解锁的实现

9宫格图形解锁的操作就是在9个点上进行的,所以我们先定义一个点类,该类主要用于存储点的信息:坐标,状态,位置。

public class Point {

    //正常状态
    public static int STATE_NORMAL = 0;
    //选中状态
    public static int STATE_PRESSED = 1;
    //错误状态
    public static int STATE_ERROR = 2;

    public float x, y;

    public int index = 0, status = 0;

    public Point() {

    }

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }
}

自定义的View

  1. View的初始化先绘制9个点,点有三个状态正常,选中,错误,对应的图片资源可自由更改。并创建二维数组存储9个点的位置。
  2. onTouchEvent事件中,监听DOWN,MOVE,UP三个状态,判断起始点是否在9个点上,然后判断触摸移动过程中经过哪些点,是否重复,记录到List中。
  3. 触摸过程中使用postInvalidate()刷新View,根据List中的点绘制点与点之间的连线。
  4. 触摸结束后,根据点的位置,判读点的个数是否足够,密码是否正确等,使用handler发送消息postInvalidate()刷新View,重新绘制点和线的样式,返回回调结果。

ps:mPassword变量为图形解锁的密码,需要提前赋值,默认为null。

public class GraphicLockView extends View {
    /**
     * 图形解锁的密码
     * 解锁前,请给该变量赋值为你的密码
     */
    public static String mPassword;

    private Point[][] points = new Point[3][3];  //创建一个3行3列的点数组

    private boolean isInit;   //判断有没有初始化

    private boolean isSelect;  //判断手指第一次按下屏幕有没有选中点

    private boolean isFinishMove;   //表示一次完整的图案绘制是否结束

    private boolean isMoveButNotPoint;   //表示手指在移动,但是并不是九宫格中的点

    private float width, height;   //屏幕宽高

    private static final int MIN_POINT = 4;    //最小能构成密码的点数

    private float offsetsX, offsetsY; //偏移量(在这里偏移量等于大边减去小边再除以2)

    private float bitmapR;   //图片资源的半径

    private float moveX, moveY;  //手势移动的x,y坐标

    private Bitmap bpPointNormal, bpPointPressed, bpPointError;  //点的三种图片

    private Bitmap bpLinePressed, bpLineError;  //线的三种图片

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private List<Point> selectPointList = new ArrayList<>();   //储存按下的点的集合

    private Matrix matrix = new Matrix();  //矩阵,用来处理线的缩放

    private OnGraphicLockListener onGraphicLockListener;   //对外的监听器

    public GraphicLockView(Context context) {
        super(context);
    }

    public GraphicLockView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public GraphicLockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setOnGraphicLockListener(OnGraphicLockListener onGraphicLockListener) {
        this.onGraphicLockListener = onGraphicLockListener;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //初始化,只执行一次即可
        if (!isInit) {
            //初始化点
            initPoints();
        }
        //绘制——将点绘制到画布上
        pointToCanvas(canvas);
        //绘制刷新时,根据点绘制连线
        if (selectPointList.size() > 0) {
            Point startPoint = selectPointList.get(0);
            //绘制九宫格坐标里的点
            for (int i = 0; i < selectPointList.size(); i++) {
                Point endPoint = selectPointList.get(i);
                lineToCanvas(canvas, startPoint, endPoint);
                startPoint = endPoint;
            }
            //绘制九宫格坐标以外的点
            if (isMoveButNotPoint) {
                lineToCanvas(canvas, startPoint, new Point(moveX, moveY));
            }
        }
    }

    /**
     * 初始化点
     */
    private void initPoints() {
        //1.根据屏幕尺寸,计算偏移量
        width = getWidth();
        height = getHeight();
        if (width > height) {   //横屏
            //横屏时只有x坐标有偏移量
            offsetsX = (width - height) / 2;
            width = height;
        } else {   //竖屏
            //竖屏时只有y坐标有偏移量
            offsetsY = (height - width) / 2;
            height = width;
        }
        //2。指定资源文件
        bpPointNormal = BitmapFactory.decodeResource(getResources(), R.drawable.point_normal);
        bpPointPressed = BitmapFactory.decodeResource(getResources(), R.drawable.point_pressed);
        bpPointError = BitmapFactory.decodeResource(getResources(), R.drawable.point_error);
        bpLinePressed = BitmapFactory.decodeResource(getResources(), R.drawable.line_pressed);
        bpLineError = BitmapFactory.decodeResource(getResources(), R.drawable.line_error);
        //3.点的坐标
        //第一排
        points[0][0] = new Point(offsetsX + width / 4, offsetsY + height / 4);
        points[0][1] = new Point(offsetsX + width / 2, offsetsY + height / 4);
        points[0][2] = new Point(offsetsX + width - width / 4, offsetsY + height / 4);
        //第二排
        points[1][0] = new Point(offsetsX + width / 4, offsetsY + height / 2);
        points[1][1] = new Point(offsetsX + width / 2, offsetsY + height / 2);
        points[1][2] = new Point(offsetsX + width - width / 4, offsetsY + height / 2);
        //第三排
        points[2][0] = new Point(offsetsX + width / 4, offsetsY + height - height / 4);
        points[2][1] = new Point(offsetsX + width / 2, offsetsY + height - height / 4);
        points[2][2] = new Point(offsetsX + width - width / 4, offsetsY + height - height / 4);
        //4.计算图片资源的半径
        bitmapR = bpPointNormal.getWidth() / 2;
        //5.设置密码按键,初始化每个点,设置为1——9
        int index = 1;
        for (int i = 0; i < points.length; i++) {
            for (int j = 0; j < points[i].length; j++) {
                points[i][j].index = index;
                index++;
            }
        }
        //初始化完成
        isInit = true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        moveX = event.getX();
        moveY = event.getY();
        isFinishMove = false;
        isMoveButNotPoint = false;
        Point point = null;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //每次手指按下的时候都表示重新绘制图案
                resetPoint();
                //检查当前按下的点与九宫格中的九个点是否吻合
                point = checkSelectPoint();
                if (point != null) {
                    isSelect = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (isSelect) {
                    point = checkSelectPoint();
                    if (point == null) {
                        isMoveButNotPoint = true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                isFinishMove = true;
                isSelect = false;
                break;
        }
        //选中重复检查
        if (!isFinishMove && isSelect && point != null) {
            if (checkCrossPoint(point)) { //交叉点
                isMoveButNotPoint = true;
            } else {//非交叉点(新的点)
                point.status = Point.STATE_PRESSED;
                selectPointList.add(point);
            }
        }
        //绘制结束
        if (isFinishMove && onGraphicLockListener != null) {
            //绘制不成立
            if (selectPointList.size() == 1) {
                resetPoint();
            } else if (selectPointList.size() < MIN_POINT && selectPointList.size() > 0) { //绘制错误,点不够
                onGraphicLockListener.LockShort();
                errorPoint();
            } else if (selectPointList.size() >= MIN_POINT) {//绘制成功
                StringBuilder strPassword = new StringBuilder();
                for (Point pwdPoint : selectPointList) {
                    strPassword.append(pwdPoint.index);
                }
                if (TextUtils.isEmpty(mPassword)) {
                    onGraphicLockListener.LockSuccess(0, strPassword.toString());
                    correctPoint();
                } else {
                    if (mPassword.equals(strPassword.toString())) {
                        onGraphicLockListener.LockSuccess(1, strPassword.toString());
                        correctPoint();
                    } else {
                        onGraphicLockListener.LockFailure();
                        errorPoint();
                    }
                }

            }
        }
        //刷新view,会调用onDraw方法
        postInvalidate();
        return true;
    }

    /**
     * 检查交叉点
     *
     * @param point 点
     * @return 是否交叉
     */
    private boolean checkCrossPoint(Point point) {
        return selectPointList.contains(point);
    }

    /**
     * 设置绘制不成立
     */
    public void resetPoint() {
        //将点的状态还原
        for (Point point : selectPointList) {
            point.status = Point.STATE_NORMAL;
        }
        selectPointList.clear();
    }

    /**
     * 设置绘制错误,将点的状态还原
     */
    public void errorPoint() {
        for (Point point : selectPointList) {
            point.status = Point.STATE_ERROR;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.sendEmptyMessage(0x001);
            }
        }).start();
    }

    /**
     * 设置绘制成功,将点的状态还原
     */
    private void correctPoint() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.sendEmptyMessage(0x001);
            }
        }).start();
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0x001) {
                for (Point point : selectPointList) {
                    point.status = Point.STATE_NORMAL;
                }
                selectPointList.clear();
                postInvalidate();
            }
        }
    };

    private Point checkSelectPoint() {
        for (int i = 0; i < points.length; i++) {
            for (int j = 0; j < points[i].length; j++) {
                Point point = points[i][j];
                if (LockUtil.isCoincide(point.x, point.y, bitmapR, moveX, moveY)) {
                    return point;
                }
            }
        }
        return null;
    }

    /**
     * 将点绘制到画布上
     *
     * @param canvas 画布
     */
    private void pointToCanvas(Canvas canvas) {
        //遍历点的集合
        for (int i = 0; i < points.length; i++) {
            for (int j = 0; j < points[i].length; j++) {
                Point point = points[i][j];
                if (points[i][j].status == Point.STATE_PRESSED) {
                    canvas.drawBitmap(bpPointPressed, point.x - bitmapR, point.y - bitmapR, mPaint);
                } else if (points[i][j].status == Point.STATE_ERROR) {
                    canvas.drawBitmap(bpPointError, point.x - bitmapR, point.y - bitmapR, mPaint);
                } else {
                    canvas.drawBitmap(bpPointNormal, point.x - bitmapR, point.y - bitmapR, mPaint);
                }
            }
        }
    }

    /**
     * 将线绘制到画布上
     *
     * @param canvas     画布
     * @param startPoint 开始的点
     * @param endPoint   结束的点
     */
    private void lineToCanvas(Canvas canvas, Point startPoint, Point endPoint) {
        float lineLength = (float) LockUtil.twoPointDistance(startPoint, endPoint);
        float degree = LockUtil.getDegrees(startPoint, endPoint);
        canvas.rotate(degree, startPoint.x, startPoint.y);  //旋转
        if (startPoint.status == Point.STATE_PRESSED) {  //按下的状态
            //设置线的缩放比例,在这里线是往一个方向缩放的,即x轴,我们只需要设置x轴的缩放比例即可,y轴默认为1
            matrix.setScale(lineLength / bpLinePressed.getWidth(), 1);
            matrix.postTranslate(startPoint.x - bpLinePressed.getWidth() / 2, startPoint.y - bpLinePressed.getHeight() / 2);
            canvas.drawBitmap(bpLinePressed, matrix, mPaint);
        } else if (startPoint.status == Point.STATE_ERROR) {//错误的状态
            matrix.setScale(lineLength / bpLineError.getWidth(), 1);
            matrix.postTranslate(startPoint.x - bpLineError.getWidth() / 2, startPoint.y - bpLineError.getHeight() / 2);
            canvas.drawBitmap(bpLineError, matrix, mPaint);
        }
        canvas.rotate(-degree, startPoint.x, startPoint.y);  //把旋转的角度转回来
    }

    /**
     * 图案监听器
     */
    public interface OnGraphicLockListener {

        void LockSuccess(int what, String password);//what=0设置密码成功回调;what=1解锁成功回调

        void LockFailure();//解锁失败的回调

        void LockShort();//密码太短的回调
    }
}

View中使用的方法

public class LockUtil {
    /**
     * 两点之间的距离
     *
     * @param a 第一个点
     * @param b 第二个点
     * @return 距离
     */
    public static double twoPointDistance(Point a, Point b) {
        //x轴差的平方加上y轴的平方,然后取平方根
        return Math.sqrt(Math.abs(a.x - b.x) * Math.abs(a.x - b.x) + Math.abs(a.y - b.y) * Math.abs(a.y - b.y));
    }

    /**
     * 判断手指移动的坐标与点的坐标是否重合(默认小于点半径的一半的时候表示重合)
     *
     * @param pointX 点横坐标
     * @param pointY 点纵坐标
     * @param r      点半径
     * @param moveX  手指移动的横坐标
     * @param moveY  手指移动的纵坐标
     * @return
     */
    public static boolean isCoincide(float pointX, float pointY, float r, float moveX, float moveY) {
        return Math.sqrt((pointX - moveX) * (pointX - moveX) + (pointY - moveY) * (pointY - moveY)) < r;
    }

    /**
     * 获取角度
     *
     * @param pointA 第一个点
     * @param pointB 第二个点
     * @return
     */
    public static float getDegrees(Point pointA, Point pointB) {
        return (float) Math.toDegrees(Math.atan2(pointB.y - pointA.y, pointB.x - pointA.x));
    }
}

设置图形密码

初始的图形密码为null,将第一次绘制成功的图形密码赋值给GraphicLockView.mPassword,作为再次绘制验证的初始密码。再次绘制成功后,使用SharedPreferences存储图形密码。

public class SettingActivity extends AppCompatActivity {
    private GraphicLockView graphicLockView;
    private TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setting);
        text = findViewById(R.id.tv_text);
        text.setText("绘制解锁图案");
        graphicLockView = findViewById(R.id.lock_view);
        graphicLockView.setOnGraphicLockListener(new GraphicLockView.OnGraphicLockListener() {

            @Override
            public void LockSuccess(int what, String password) {
                if (what == 0) {
                    GraphicLockView.mPassword = password;
                    text.setText("再次绘制解锁图案");
                } else {
                    SPUtil.put(SettingActivity.this, "PASSWORD", password);
                    SettingActivity.this.finish();
                }
            }

            @Override
            public void LockFailure() {
                text.setText("与上次绘制的不一致");
            }

            @Override
            public void LockShort() {
                text.setText("最少连接4个点");
            }
        });
    }
}

解锁图形密码

图形密码设置成功后,该密码就是下次解锁的密码。根据回调结果做判断,进行相应的逻辑处理即可。

public class UnlockActivity extends AppCompatActivity {
    private GraphicLockView graphicLockView;
    private TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setting);
        text = findViewById(R.id.tv_text);
        text.setText("请输入手势密码");
        graphicLockView = findViewById(R.id.lock_view);
        graphicLockView.setOnGraphicLockListener(new GraphicLockView.OnGraphicLockListener() {

            @Override
            public void LockSuccess(int what, String password) {
                text.setText("解锁成功");
            }

            @Override
            public void LockFailure() {
                text.setText("密码错误");
            }

            @Override
            public void LockShort() {
                text.setText("最少连接4个点");
            }
        });
    }
}

重置密码

清除SharedPreferences中密码对应的key或者直接将密码的key赋值为空,即可。

参考

https://www.jianshu.com/p/85315f428222

项目地址

https://github.com/MyAndroidDemo/GraphicUnlock

2016-11-09 11:17:25 u010550374 阅读数 1077

工作中有幸接触到了韩文显示和韩文输入法法,然而对于不懂韩文的我来说,要我写输入法真的是非常的困难,百度一点有用的资料都没有,翻墙去谷歌搜索也没有,最后可以提供了一个文档,这个文档是非常的有用的,他实现的过程也很简单,韩国的输入方式是笔画的,类似于我国的五笔输入,hangul一般需要三个音首音、中音、尾音组合而成。

最后通过算法组合算出对应的Unicode 编码


9宫格只是把其中的首音、中音、尾音、简化后在重新组合成的。


基本的实现过程就是这样了,当然要实现完整的9宫格还要有一套完整的算法,我是参照苹果输入法的,这里我就不贴出来了,算法是我自己写的。过程非常繁琐。


2013-04-08 14:53:22 duanhai189 阅读数 3993

iOS 的9宫格实现方式有很多种,这里是参考了网上某某的demo后,几乎照着做了一遍。


这里我采用订制cell的方式来实现


这里给出几点注意事项:

1,订制的cell里面的重用标识符一定要和代码中的标识符一样。不然重用机制不能生效

#pragma mark

#pragma mark -UITalbeViewCellDelegate


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *cellIdentifier = @"ViewCell";

    DH_Cell *cell = (DH_Cell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil) {

        

      cell =  [[[NSBundle mainBundle] loadNibNamed:@"DH-Cell" owner:self options:nil] objectAtIndex:0];

//        [[NSBundle mainBundle] loadNibNamed:@"DH-Cell" owner:self options:nil];

//        cell = viewCell;

        cell.delegate = self;


    }

    //取消行选中色

    cell.selectionStyle = UITableViewCellSelectionStyleNone;


    

    if ((indexPath.row*3)<=([mItemArray count]-1))

    {

        CellObject * i = [mItemArray objectAtIndex:indexPath.row*3];

        cell.lab1.text = [NSString stringWithFormat:@"%@",i.Title];

        [cell.btn1 setImage:[UIImage imageNamed:        [NSString stringWithFormat:@"%@",i.Image]] forState:UIControlStateNormal];

        //nib cell中没有设置tag,这里设置tag

        [cell.btn1 setTag:indexPath.row*3];

        

        //单个隐藏第2.3

        if (indexPath.row == mItemArray.count/3) {

            cell.btn2.hidden = YES;

            cell.btn3.hidden = YES;

            cell.lab2.hidden = YES;

            cell.lab3.hidden = YES;

        }

        

        

    }

    if ((indexPath.row*3+1)<=([mItemArray count]-1))

    {

        CellObject * i = [mItemArray objectAtIndex:indexPath.row*3+1];

        cell.lab2.text = [NSString stringWithFormat:@"%@",i.Title];

        [cell.btn2 setImage:[UIImage imageNamed:        [NSString stringWithFormat:@"%@",i.Image]] forState:UIControlStateNormal];

        [cell.btn2 setTag:indexPath.row*3+1];

        

        if (indexPath.row == mItemArray.count/3) {

            cell.btn3.hidden = YES;

            cell.lab3.hidden = YES;

        }

    }

    if ((indexPath.row*3+2)<=([mItemArray count]-1))

    {

        CellObject * i = [mItemArray objectAtIndex:indexPath.row*3+2];

        cell.lab3.text = [NSString stringWithFormat:@"%@",i.Title];

        [cell.btn3 setImage:[UIImage imageNamed:        [NSString stringWithFormat:@"%@",i.Image]] forState:UIControlStateNormal];

        [cell.btn3 setTag:indexPath.row*3+2];

    }


    

    return cell;

}





代码我也一并附上,代码里面关键地方有注释,给初学的同学看看。

demo地址:


http://pan.baidu.com/share/link?shareid=434473&uk=2315407450

自定义 9宫格抽奖

阅读数 123

9宫格迷宫算法

阅读数 144

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