详解Android登陆界面用户协议解决方案

先上一张图来看要实现的东西

用户协议.png

一般来说每个app都有这个用户协议阅读相关的功能,之前做的都是一个协议,也都是单行的,完全没有复杂度,可以一个checkbox加上一个textview来搞定,那么像图上这种复杂的该怎们实现呢.

来看他有神们不同,有那些难点

1,选中框被文字包裹,单纯的checkbox和textview无法实现,因为选中框会在文字左方

2,协议文件有很多,不定项,文件是服务器返回的,而且每个文件中间都会有一个颜色不一样的点隔开

3,为每个文件都有点击事件,点击文件会产看对应的详情.....

其实这样一看很多人都知道可以用textview的span来搞定,算盘的想过内容就不复习了,直接上代码

首先模拟一个协议数据,创建一个是否阅读的变量

String[] protocols = {
      "《创客中心产品认购合同》",
      "《创客中心注册申请合同》",
      "《创客中心系统服务合同》",
      "《创客中心服务合同》",
      "《代理协议》"
  };
 private boolean isChecked;

然后我们为搞一个字符串,第一位来个空格作为图片的替换

接着我们创建一个该字符串的SpannableStringBuilder,然后调用setIconSapn方法为该字符串的第一个字符替换成图标(默认为位选中状态),setIconSapn方法在下面

然后我们为第一个字符位置设置一个点击事件imagClick ,根据对应的选中状态做图标的变化

final String string = " 已阅读并同意";
    //图标(默认位选中)
    spannableStringBuilder = new SpannableStringBuilder(string);
    setIconSapn(spannableStringBuilder, R.mipmap.app_login_unchecked);
    //选择按钮的点击事件
    ClickableSpan imagClick = new ClickableSpan() {
      @Override
      public void onClick(View widget) {
        //显示协议内容
        if (isChecked) {
          setIconSapn(spannableStringBuilder, R.mipmap.app_login_unchecked);
        } else {
          setIconSapn(spannableStringBuilder, R.mipmap.app_login_checked);
        }
        isChecked = !isChecked;
        mView.setProtocl(spannableStringBuilder);
      }

      @Override
      public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        ds.setUnderlineText(false);
        ds.setColor(Color.WHITE);
      }
    };
    spannableStringBuilder.setSpan(imagClick, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

setIconSapn方法

/**
   * 设置徐泽状态图标
   *
   * @param spannableStringBuilder
   * @param resId
   */
  private void setIconSapn(SpannableStringBuilder spannableStringBuilder, int resId) {
    MyImageSpan imageSpan = new MyImageSpan(mContext, BitmapFactory.decodeResource(mView.getResources(), resId), 2);
    spannableStringBuilder.setSpan(imageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  }

这里可以看到我没有用系统的ImageSpan,因为该文字存在换行,系统的ImageSpan图标无法进行居中,所以我们自定义一个ImageSpan,重写draw方法,解决了该问题,代码如下

@Override
  public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom,
           Paint paint) {

    //draw 方法是重写的ImageSpan父类 DynamicDrawableSpan中的方法,在DynamicDrawableSpan类中,虽有getCachedDrawable(),
    // 但是私有的,不能被调用,所以调用ImageSpan中的getrawable()方法,该方法中 会根据传入的drawable ID ,获取该id对应的
    // drawable的流对象,并最终获取drawable对象
    Drawable drawable = getDrawable(); //调用imageSpan中的方法获取drawable对象
    canvas.save();

    //获取画笔的文字绘制时的具体测量数据
    Paint.FontMetricsInt fm = paint.getFontMetricsInt();

    //系统原有方法,默认是Bottom模式)
    int transY = bottom - drawable.getBounds().bottom;
    if (mVerticalAlignment == ALIGN_BASELINE) {
      transY -= fm.descent;
    } else if (mVerticalAlignment == ALIGN_FONTCENTER) {  //此处加入判断, 如果是自定义的居中对齐
      //与文字的中间线对齐(这种方式不论是否设置行间距都能保障文字的中间线和图片的中间线是对齐的)
      // y+ascent得到文字内容的顶部坐标,y+descent得到文字的底部坐标,(顶部坐标+底部坐标)/2=文字内容中间线坐标
      transY = ((y + fm.descent) + (y + fm.ascent)) / 2 - drawable.getBounds().bottom / 2;
    }

    canvas.translate(x, transY);
    drawable.draw(canvas);
    canvas.restore();
  }

紧接着我们遍历拿到的协议组,挨个添加到之前的string中,为每个协议设置为蓝色,并设置点击事件,最后返回最终的SpannableStringBuilder (先添加点击事件,否则前景色会被点击事件的颜色淡化)

for (int i = 0; i < protocols.length; i++) {
      final String protocol = protocols[i];
      SpannableStringBuilder protocolStringBuild = new SpannableStringBuilder(protocol);
      //协议
      //点击span
      final int finalI = i;
      ClickableSpan clickableSpan = new ClickableSpan() {
        @Override
        public void onClick(View widget) {
          //显示协议内容
          mView.showProtocol(protocol, finalI, protocols.length);
        }

        @Override
        public void updateDrawState(TextPaint ds) {
          super.updateDrawState(ds);
          ds.setUnderlineText(false);
          ds.setColor(Color.WHITE);
        }
      };
      protocolStringBuild.setSpan(clickableSpan, 0, protocol.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
      //前景
      ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(mView.getResources().getColor(R.color.colorPrimary));
      protocolStringBuild.setSpan(foregroundColorSpan, 0, protocol.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
      spannableStringBuilder.append(protocolStringBuild);
      //点
      if (i != protocols.length - 1) {
        SpannableStringBuilder dotStringBuild = new SpannableStringBuilder("、");
        ForegroundColorSpan dotSpan = new ForegroundColorSpan(mView.getResources().getColor(R.color.color_66));
        dotStringBuild.setSpan(dotSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        spannableStringBuilder.append(dotStringBuild);
      }
    }
    return spannableStringBuilder;

最后上一张效果图,不知为何录屏相当不清晰

协议.gif

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android登陆界面用户名检测功能

    今天分享一下登陆界面用户登录名的检测,大家都知道如果在服务器端进行所有用户名的检测是比较浪费资源的.用户每点击一次登陆就要发到服务端去检测,对于服务端来说负荷是比较大的.所以呢在客服端对用户的非法信息进行简单的过滤是非常有必要的. 源码下载:Android用户名检测 首先看一下效果: 当用户输入的用户名长度小于3,或者大于9时将出现红色提示,并且登陆按钮不可点击. 当输入的用户名大在合法区间则提示消失,如果密码不为空则登陆按钮可点击 虽然功能很小却用到了不少的东西: EditText失去焦点事件

  • Android仿新浪微博启动界面或登陆界面(1)

    本文为大家分享了Android模仿新浪微博启动界面&登陆界面的具体实现代码,供大家参考,具体内容如下 启动界面 主要有两个功能: 1.加载启动动画 2.判断网络,有者直接进入登陆界面,否则去设置网络 代码较简单,主要采用AlphaAnimation()方法和动画监听器,使一张图片产生渐变动画.在动画启动的时候判断网络,动画结束时完成判断并进入登陆界面. /** * Created by D&LL on 2016/5/25. * 初始页面加载界面 */ public class Splash

  • Android开发之完成登陆界面的数据保存回显操作实例

    本文实例讲述了Android开发之完成登陆界面的数据保存回显操作.分享给大家供大家参考,具体如下: LoginActivity.java: package com.example.login; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.view.Menu; import android.view

  • Android实现带有记住密码功能的登陆界面

    本文实例为大家分享了Android带有记住密码功能的登陆界面实现代码,供大家参考,具体内容如下 1.设计思路 主要采用SharedPreferences来保存用户数据,本Demo没有经过加密,所有一旦Android系统被ROOT的话,其他用户就可以查看用户的私有目录,密码文件就很不安全.所以真正应用在软件上面的,一定要经过加密才保存,可以选择MD5加密. SharedPreferences介绍可以参看这篇博文:http://www.jb51.net/article/84859.htm TextW

  • Android登陆界面实现清除输入框内容和震动效果

    本文为大家分享Android登陆界面实现清除输入框内容和震动效果的全部代码,具体内容如下: 效果图: 主要代码如下 自定义的一个EditText,用于实现有文字的时候显示可以清楚的按钮: import android.content.Context; import android.graphics.drawable.Drawable; import android.text.Editable; import android.text.TextWatcher; import android.uti

  • 详解Android登陆界面用户协议解决方案

    先上一张图来看要实现的东西 用户协议.png 一般来说每个app都有这个用户协议阅读相关的功能,之前做的都是一个协议,也都是单行的,完全没有复杂度,可以一个checkbox加上一个textview来搞定,那么像图上这种复杂的该怎们实现呢. 来看他有神们不同,有那些难点 1,选中框被文字包裹,单纯的checkbox和textview无法实现,因为选中框会在文字左方 2,协议文件有很多,不定项,文件是服务器返回的,而且每个文件中间都会有一个颜色不一样的点隔开 3,为每个文件都有点击事件,点击文件会产

  • 详解Android Studio实现用户登陆界面demo(xml实现)

    使用Android Studio 编写的第一个demo,使用布局文件-xml实现用户登录界面 注:所建工程均为Android 6.0 所以只要是Android 6.0(包括6.0)以上的真机,模拟机都可以使用 Step1:Android Studio 开发环境的搭建: 1.安装JDK (1.8): 2.安装Android studio (3.3.1) 包含 gradle.sdk manage .avd manage : 3.使用sdk manage 下载安装 sdk: 4.使用avd manag

  • 详解android 中文字体向上偏移解决方案

    在开发 webapp 时,发现在 android 端的中文会莫名其妙的向上偏移.为了解决这个问题,尝试了很多方法,最后使用以下解决方案. 1.bug 出现 目前在开发 webapp,在调试的时候,发现项目里面的中文有一点向上偏移.具体表现为:使用开发者工具去查看元素,元素的真实高度和位置与文字不同.列如,一个span的font-size和line-height都设置为16px,在调试时,元素的高度确实是16px,但是,中文的高度看起来并不止16px,而且显示的位置明显超出了元素的尺寸范围,向上偏

  • 详解Android 基于TCP和UDP协议的Socket通信

    本来想讲一下基础的网络通信方面的知识点,发现太枯燥乏味了,不过笔试中也经常会问到这方面的问题,所以关于通信方面的知识点,小编会放到面试中去,因为实战中也就面试会用到这方面知识点 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据. 而Socket通信中基于TCP/IP协议的通信则是在双方建立起连接后就可以直接进行数

  • 详解android在mob平台实现qq登陆和分享

    个人感觉mob平台功能还是比较强大的,很多功能都可以通过他们平台来实现. 建议仔细观看每一个步骤,如果一个步骤没处理好,可能就会让你的这个功能无法实现.相信我一定可以成功的. 废话少说,先看一下效果: 1.在mob平台配置ShareSDK环境 1.如何在mob平台创建应用 下面为我创建的应用,如图所示,我们选择接入的接口为ShareSDK 2.获取你的App Key和App Secret(建议用自己的) 获取你先创建应用的App Key和App Secret,这里主要告诉你在哪里找App Key

  • 详解Android Automotive车载应用对驾驶模式Safe Drive Mode的适配

    前言 最近在Android Automotive 上遇到的一些问题,有好几个都跟Android 车载操作系统上应用的驾驶模式有关,国内这方面的资料很少,自己在这里总结一下相关的知识,主要包含下面几个方面: Android Automotive 和 Android Auto的区别 Android Automotive 的驾驶模式介绍 Android Automotive 实现驾驶模式的几种实现方式和代码示例,以及实现效果 主要是还是想总结一下Android 车载应用对Automotive 驾驶模式

  • 详解Android更改APP语言模式的实现过程

    一.效果图 二.描述 更改Android项目中的语言,这个作用于只用于此APP,不会作用于整个系统 三.解决方案 (一)布局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" a

  • 详解Android中获取软键盘状态和软键盘高度

    详解Android中获取软键盘状态和软键盘高度 应用场景 在Android应用中有时会需要获取软键盘的状态(即软键盘是显示还是隐藏)和软键盘的高度.这里列举了一些可能的应用场景. 场景一 当软键盘显示时,按下返回键应当是收起软键盘,而不是回退到上一个界面,但部分机型在返回键处理上有bug,按下返回键后,虽然软键盘会自动收起,但不会消费返回事件,导致Activity还会收到这次返回事件,执行回退操作,这时就需要判断,如果软键盘刚刚由显示变为隐藏状态,就不执行回退操作. 场景二 当软键盘弹出后,会将

  • 详解Android Bitmap的常用压缩方式

    一.前言 已经好久没有更新博客,大概有半年了,主要是博主这段时间忙于找工作,Android岗位的工作真的是越来越难找,好不容易在广州找到一家,主要做海外产品,公司研发实力也不错,所以就敲定了三方协议.现在已经在公司实习了一个月多,目前主要是负责公司某个产品的内存优化,刚好就总结了一下Android Bitmap常用的优化方式. Android中的图片是以Bitmap方式存在的,绘制的时候也是Bitmap,直接影响到app运行时的内存,在Android,Bitmap所占用的内存计算公式是:图片长度

  • 详解Android系统启动过程

    计算机是如何启动的 计算机的硬件包括:CPU,内存,硬盘,显卡,显示器,键盘鼠标等输入输出设备.所有的软件都是存放在硬盘中,程序执行时,需要将程序从硬盘上读取到内存中,然后加载到CPU中来运行.当按下开机键时,内存中什么都没有,因此需要借助某种方式,将操作系统加载到内存中,而完成这项任务的就是BIOS. 引导阶段 BIOS:BIOS是主板芯片上的一个程序,计算机通电后,第一件事情就是读取BIOS. BIOS首先进行硬件检测,检查计算机硬件能否满足运行的基本条件.如果硬件出现问题,主板发出不同的蜂

随机推荐