简介面向Android初中级开发者的登录注册界面源码适合在课程设计、毕业设计或实际商业项目起步阶段参考重点解决首屏登录/注册场景中界面粗糙、交互生硬的问题。压缩包共52个文件大小1.27MB包含15个XML布局、13张PNG切图、3个Java源文件、2个jar依赖库及可直接安装的APK目录结构清晰便于对照布局与逻辑关系逐层理解。资源围绕Material Design规范组织覆盖TextInputLayout浮动标签、密码明文/密文切换、MaterialButton样式、页面跳转与轻量动画过渡等实现细节同时融入了输入校验、错误提示、本地数据保存等常见需求的处理思路并提供了完整工程与演示APK可直接运行查看效果。已有6483人浏览学习适合希望通过完整案例提升Android界面设计与开发能力的读者对照源码可快速熟悉依赖库引入、工程目录组织与常见适配细节减少重复踩坑。1. 登录注册界面源码先看它值不值得拼进自己的工程再决定怎么改别人发过来的登录注册界面源码截图往往很漂亮真正往自己工程里拼的时候才暴露问题状态栏和标题叠在一起、软键盘弹出来把输入框顶没了、按钮按下去没有任何视觉反馈。这份标题里的源码价值点其实不在“好看”二字而在控件状态、背景资源、间距规范这三层有没有做完整。我拿这类界面包做的第一件事是建一个全新的空工程把登录和注册两个布局分别加载排除依赖关系后再决定哪些控件可以直接复用。适合正在写正式 App 首版、课程设计演示、企业内部工具登录页的开发者。下面按布局骨架、背景形态、Activity 绑定、真机适配、深色模式这一条线拆完你会清楚这份资源最终能给你留下什么。2. 布局骨架为什么登录页多用 LinearLayout注册页反而要上约束布局2.1 LinearLayout 竖向流式结构登录页最不容易出问题的容器选择登录页面从视觉结构上看大多是上下排列顶部 Logo、标题文字、手机号输入框、密码输入框、登录按钮、注册入口。这种一列到底的结构用LinearLayout是最稳的。原因不复杂LinearLayout按orientation顺序排列子控件没有复杂的坐标关系layout_marginTop直接控制元素间距新开发者改起来也不容易把控件改到屏幕外。我拆这份界面源码时先看的也是登录页最外层是不是LinearLayout。如果是说明作者至少没把页面结构做复杂。登录页典型结构如下!-- 登录页外层容器路径layout/activity_login.xml -- LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/android android:layout_widthmatch_parent android:layout_heightmatch_parent android:orientationvertical android:gravitycenter_horizontal android:paddingStart24dp android:paddingTop48dp android:paddingEnd24dp ImageView android:idid/iv_logo android:layout_width80dp android:layout_height80dp android:importantForAccessibilityno android:srcdrawable/ic_logo / TextView android:idid/tv_title android:layout_widthwrap_content android:layout_heightwrap_content android:layout_marginTop12dp android:text欢迎回来 android:textColor#222222 android:textSize28sp / EditText android:idid/et_phone android:layout_widthmatch_parent android:layout_height48dp android:layout_marginTop32dp android:backgrounddrawable/bg_input_normal android:drawableStartdrawable/ic_phone android:drawablePadding8dp android:hint请输入手机号 android:inputTypephone android:maxLines1 android:paddingStart16dp android:paddingEnd16dp / EditText android:idid/et_password android:layout_widthmatch_parent android:layout_height48dp android:layout_marginTop16dp android:backgrounddrawable/bg_input_normal android:hint请输入密码 android:inputTypetextPassword android:maxLines1 android:paddingStart16dp android:paddingEnd16dp / Button android:idid/btn_login android:layout_widthmatch_parent android:layout_height48dp android:layout_marginTop32dp android:backgrounddrawable/bg_btn_login android:text登 录 android:textColor#FFFFFF android:textSize16sp / /LinearLayout这段代码里有几个参数值得注意。输入框高度统一写成48dp因为大多数设计规范里可点击控件的最小触摸高度是 48dp再小容易误触。输入框宽度写成match_parent配合父容器的左右24dp内边距就能自动适配不同屏幕宽度不用再额外算宽度。paddingStart和paddingEnd写的是输入文字与边框之间的距离不是输入框与屏幕的距离。很多新手在这里把 margin 和 padding 混掉导致文字贴着圆角边框视觉上非常挤。drawableStart用于在输入框左侧加一个小图标drawablePadding控制图标和文字之间的距离这里给了8dp实际效果比默认的 4dp 更宽松。文本的textSize用sp控件的宽高用dp这个规则后面避坑章节还会展开。这段布局唯一的缺点是Button自带的阴影在某些定制主题下会有一圈灰色边真机预览和设计稿有差异处理办法我放到第三章的 selector 部分讲。2.2 ConstraintLayout 在注册页的价值减少嵌套但约束必须闭环注册页通常比登录页多几个控件头像、昵称、手机号、验证码、协议复选框。如果全用LinearLayout嵌套层级会到三层以上界面加载时测量和绘制的耗时成倍增加。这就是源码里注册页选择ConstraintLayout的直接原因用一条“约束链”把控件之间的关系画出来层级扁平性能更好。但约束布局有个明显的入门门槛约束不写闭环控件就会跑到屏幕边缘。这里给一个注册页常见的“头像 昵称输入框”组合!-- 注册页局部路径layout/activity_register.xml -- androidx.constraintlayout.widget.ConstraintLayout android:layout_widthmatch_parent android:layout_heightwrap_content android:paddingHorizontal24dp ImageView android:idid/iv_avatar android:layout_width24dp android:layout_height24dp android:srcdrawable/ic_avatar app:layout_constraintStart_toStartOfparent app:layout_constraintTop_toTopOfparent / EditText android:idid/et_nickname android:layout_width0dp android:layout_height48dp android:layout_marginStart12dp android:hint请输入昵称 android:maxLines1 app:layout_constraintEnd_toEndOfparent app:layout_constraintStart_toEndOfid/iv_avatar app:layout_constraintTop_toTopOfparent / View android:idid/divider_line android:layout_width0dp android:layout_height1dp android:background#E6E9F0 app:layout_constraintEnd_toEndOfparent app:layout_constraintStart_toStartOfparent app:layout_constraintTop_toBottomOfid/et_nickname / /androidx.constraintlayout.widget.ConstraintLayout核心就在et_nickname这条约束上layout_width0dp同时约束了起点到头像的end终点到父容器end。0dp在ConstraintLayout里表示“填充剩余空间”配合两端约束昵称输入框会自动占满头像右侧到屏幕右边的区域。这是约束布局里最常用的写法源码里大量出现。很多从LinearLayout转过来的开发者会把layout_widthwrap_content留在EditText上然后只约束一端结果输入框宽度随内容变化点击区域忽大忽小。记住一条经验约束布局里想撑满一行就用0dp不要再学match_parent的旧写法。至于那个divider_line高度只有1dp作用是在输入框下面画一条细细的分割线。这里用View而不是ImageView因为View没有额外绘制开销改颜色也只改background一个属性后续想换掉整条线的色值非常方便。3. 界面颜值的关键shape 背景、selector 按压状态与间距细节3.1 用 shape 画出输入框的圆角、描边和浅底色真正让登录注册界面“好看”的通常不是复杂图片而是几个简单的 drawable 背景。输入框最常见的样式是浅灰底、细描边、小圆角。这些用一张纯色 PNG 也能做但换机型、换主题后会失真源码包里的做法是直接用 XML 写的 shape 文件这才是最值得留下的部分。!-- 输入框默认背景路径drawable/bg_input_normal.xml -- shape xmlns:androidhttp://schemas.android.com/apk/res/android !-- 填充底色 -- solid android:color#F5F6FA / !-- 边框颜色与宽度 -- stroke android:width1dp android:color#D8DCE4 / !-- 圆角半径 -- corners android:radius8dp / /shape参数很好理解。solid的#F5F6FA是偏冷的浅灰比纯白更柔和也能让后续的hint提示文字更清晰。stroke只画了1dp的边框颜色#D8DCE4灰度比底色深一档刚好在屏幕上形成一圈细边。corners的8dp圆角是针对四个角统一生效的如果只想要顶部两个角是圆角需要把corners改成topLeftRadius和topRightRadius两个属性分别写。这里有个非常隐蔽的问题shape 背景做成以后输入框获得焦点时不会自动换边框颜色。也就是说用户点进输入框看到的还是和失焦时一样的灰边。合理做法是做两个 shape一个默认态、一个聚焦态用 selector 切换。我在源码里验证时发现部分版本只给了一个 shape这就是“好看但交互不足”的典型表现。!-- 输入框聚焦背景路径drawable/bg_input_focused.xml -- shape xmlns:androidhttp://schemas.android.com/apk/res/android solid android:color#FFFFFF / stroke android:width1.5dp android:color#3D6DF4 / corners android:radius8dp / /shape再把两个文件包装成 selector!-- 输入框状态背景路径drawable/bg_et_selector.xml -- selector xmlns:androidhttp://schemas.android.com/apk/res/android item android:state_focusedtrue android:drawabledrawable/bg_input_focused / item android:drawabledrawable/bg_input_normal / /selector然后在EditText上把background改成drawable/bg_et_selector。注意 selector 里state_focused的 item 必须写在前面系统按顺序从上往下匹配第一个满足条件的就被使用。这段代码在资源包里如果缺失补上即可几行 XML 就能让输入框的交互质感提升一个台阶。3.2 登录按钮的三个视觉状态禁用、按下、默认按钮是登录页最重要的操作入口。很多源码包里的按钮只做了一张默认背景图按下去没有反应放在真机上就像“失灵”了一样。正确的做法是用 selector 管理按钮的三种状态可用、按下、不可用。!-- 登录按钮背景路径drawable/bg_btn_login.xml -- selector xmlns:androidhttp://schemas.android.com/apk/res/android !-- 不可用状态浅灰蓝 -- item android:state_enabledfalse shape solid android:color#B9C6DE / corners android:radius24dp / /shape /item !-- 按下状态透明度微调模拟按压 -- item android:state_pressedtrue shape solid android:color#3D6DF4 / corners android:radius24dp / /shape /item !-- 默认状态 -- item shape solid android:color#3D6DF4 / corners android:radius24dp / /shape /item /selector我把按下状态的可视化改成了颜色透明度的变化。实际按压时按钮会从深蓝变成半透明深蓝视觉上就像被按进屏幕里。相比把整张背景图替换成一张更暗的图片这种方案体积小也更容易维护主题色。这里有一个坑android:state_enabledfalse必须写在state_pressed之前否则按钮在不可用时仍会匹配到按下的样式。还有一个普遍问题Button组件自带默认的stateListAnimator部分主题下即使设置了background点击时还是会浮出系统阴影。不想看到阴影就在布局里给按钮加上android:stateListAnimatornull这条在真机上验证过能去掉按钮按下的“浮动动画”。3.3 1dp 分割线与文字间距界面是否精致的细节分水岭肉眼判断一个登录注册界面“精致”往往不是靠大色块而是靠 1dp 的分割线和 8dp 的间距。源码里注册页的协议说明文字是不是和复选框严格对齐就能看出作者有没有花时间打磨。我整理一份常用的间距基准页面左右边距统一24dp这是保证内容不贴屏幕边缘的基础输入框之间的垂直间距16dp输入框内部文字左侧距离16dp按钮与上方输入框的间距32dp分割线用1dp高度颜色#E6E9F0分割线颜色不能太深。#E6E9F0是接近背景的浅灰在大多数屏幕上能看见但不抢眼如果换成#CCCCCC整条线就会显得突兀把输入区切得非常生硬。间距方面不要贪多24dp、16dp、32dp这三个基准值已经能覆盖绝大多数界面场景乱加间距反而会让页面高度膨胀小屏手机上被迫滚动。4. 从布局到流程ViewBinding 绑定控件再把校验、倒计时和跳转接进去4.1 用 ViewBinding 替代 findViewById少写强转也少一个空指针点拿到登录注册界面源码以后光有 XML 布局还不能跑必须绑定到 Activity 上。老项目里常见的findViewById写法不是不能用只是每次都要写泛型强转遇到控件 id 改了就崩。源码包里的界面结构简单我更推荐直接开ViewBinding。先在模块的构建配置里打开开关android { buildFeatures { viewBinding true } }然后 Activity 里按下面写法绑定登录页class LoginActivity : AppCompatActivity() { private lateinit var binding: ActivityLoginBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding ActivityLoginBinding.inflate(layoutInflater) setContentView(binding.root) binding.btnLogin.setOnClickListener { val phone binding.etPhone.text?.toString()?.trim().orEmpty() if (phone.isEmpty()) { binding.etPhone.error 手机号不能为空 returnsetOnClickListener } // 这里再把校验通过的手机号传给注册页或下一步 } } }ActivityLoginBinding是根据activity_login.xml自动生成的类名规则是把 XML 文件名转成驼峰再加Binding后缀。.inflate(layoutInflater)负责把布局文件实例化binding.root就是整个布局的根节点直接传给setContentView。绑定之后所有带 id 的控件都会变成binding对象的属性类型是编译期确定的不再需要手写强转。etPhone.error是EditText自带的方法用于在输入框下方显示红字错误提示源码里做为空校验的反馈非常合适比用Toast轻量。注意orEmpty()的作用text?.toString()得到的可能是 null直接调用.isEmpty()会崩转换后再判断就能避开这个空指针点。4.2 手机号校验、验证码倒计时与注册页跳转登录注册界面通常还伴随着校验逻辑。源码包里如果写了CountDownTimer说明作者已经把“获取验证码”的交互做进去了。这里给一段注册页常见的倒计时代码class RegisterActivity : AppCompatActivity() { private lateinit var binding: ActivityRegisterBinding private var countDownTimer: CountDownTimer? null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding ActivityRegisterBinding.inflate(layoutInflater) setContentView(binding.root) binding.btnGetCode.setOnClickListener { startCountDown() } } private fun startCountDown() { // 防止重复点击连续创建多个倒计时 countDownTimer?.cancel() binding.btnGetCode.isEnabled false countDownTimer object : CountDownTimer(60_000, 1_000) { override fun onTick(millisUntilFinished: Long) { binding.btnGetCode.text ${millisUntilFinished / 1000}s 后重发 } override fun onFinish() { binding.btnGetCode.isEnabled true binding.btnGetCode.text 重新获取 } }.start() } override fun onDestroy() { super.onDestroy() countDownTimer?.cancel() } }CountDownTimer(60_000, 1_000)两个参数分别是总时长和 tick 间隔单位都是毫秒。总时长 60 秒每 1 秒回调一次onTick把millisUntilFinished除以 1000 得到剩余秒数直接更新按钮文字。onFinish在倒计时结束后调用这里把按钮重新置为可点击。两个细节必须注意。第一点击获取验证码后先cancel()旧计时器否则用户连点三次会创建三个计时器界面秒数会乱跳。第二onDestroy里必须cancel()否则 Activity 退出时计时器还在跑回调里又访问了已销毁的 binding会直接抛异常。这是界面源码里最容易出现的“隐藏炸弹”。注册页跳转可以顺带把数据带过去比如用户从登录页点了“立即注册”binding.tvGoRegister.setOnClickListener { val intent Intent(this, RegisterActivity::class.java) intent.putExtra(from, login) startActivity(intent) }putExtra只是一个普通的键值对登录页传login注册页在onCreate里读出来可以决定是否隐藏某个返回按钮也可以决定注册成功后要不要自动回填登录页的手机号。界面源码往往在这一块只搭了框架具体参数根据业务需求补。5. 避坑登录注册界面从预览到真机的五个翻车场景5.1 登录按钮在部分全面屏手机上被底部导航栏盖住现象布局预览里按钮还在屏幕中间偏下到了真机按钮有一部分被系统底部横条遮住点击区域点不中。 原因默认情况下setContentView的内容区域不会自动避开系统导航栏尤其是全屏手势导航的手机根布局底部控件可能延伸到导航栏下面。 解决在根布局上设置android:fitsSystemWindowstrue或者在 Activity 里手动设置窗口装饰。常见做法是给最外层LinearLayout加fitsSystemWindowsLinearLayout android:layout_widthmatch_parent android:layout_heightmatch_parent android:fitsSystemWindowstrue android:orientationvertical加完以后布局会自动把系统栏占用的空间让出来底部按钮不会再被遮挡。注意这个属性要加在根布局上不是随便套在某个子控件上否则虽然实际画面稍向上移但视觉上会出现上下空洞。5.2 软键盘弹起后输入框被顶到屏幕外面现象点击密码输入框软键盘弹起来页面没有自动往上滚动输入框被挡了一半用户看不见自己打的密码。 原因AndroidManifest.xml里对应 Activity 没有配置软键盘处理模式。默认行为在某些主题下是adjustPan键盘抬起时直接平移整个窗口一旦布局下面有按钮输入框就被挤出可视区。 解决在AndroidManifest.xml的activity节点上加入activity android:name.LoginActivity android:screenOrientationportrait android:windowSoftInputModeadjustResize /adjustResize表示键盘弹起后重新调整窗口尺寸配合根布局的fitsSystemWindows输入框会自然上移并保持在可视范围内。如果是横屏或键盘高度较大的设备建议同时把登录页根布局套一层ScrollView给足滚动空间。5.3 按钮点击时没有任何视觉反馈像卡住了一样现象按下“登录”按钮界面完全不变松开以后直接跳转或弹提示用户总觉得点歪了。 原因很多源码包把按钮背景直接设为drawable/bg_btn_default这样一个 shape 文件shape 是不响应按压状态的必须用 selector 或 ripple 包装。 解决把默认 shape 文件当作 selector 的一个 item 引进去。也就是本文第三章第一节的做法。如果项目最低支持版本在 Android 5.0 以上可以直接用 ripple把按压反馈做成涟漪扩散效果ripple xmlns:androidhttp://schemas.android.com/apk/res/android android:color#33FF5722 item android:drawabledrawable/bg_btn_default / /rippleripple外层是涟漪颜色内层item是原来的 shape 背景。按下时水波从点击位置向外扩散抬起后恢复原状。这个文件要放在drawable-v21目录下低版本会自动走默认背景不会崩。5.4 预览图和真机对比输入框里的文字靠边太近现象开发工具预览里圆角输入框文字位置正好装到真机上文字左边贴着圆角边框看着很挤。 原因EditText的paddingStart没有生效或者被主题里的默认textCursorDrawable干扰。更常见的是输入框用了Button风格背景文字默认有额外的内边距。 解决给EditText显式声明paddingStart和paddingEnd并且不要依赖 shape 文件里的 padding。shape 里的padding在某些主题下会被控件自身的 padding 覆盖所以把间距写在控件属性上EditText android:layout_widthmatch_parent android:layout_height48dp android:paddingStart16dp android:paddingEnd16dp /另外检查一下是否设置了android:drawableStart图标自带的额外内边距也会把文字推开。如果加了图标还嫌挤把drawablePadding从 8dp 改成4dp对比看效果。5.5 文字大小写成 dp真机上字号忽大忽小现象同一套布局A 手机上文字刚好B 手机上文字大了一圈甚至换行把按钮顶乱。 原因控件尺寸用了 dp 没问题但文字也写了android:textSize16dpdp 不随系统字体缩放某些 ROM 上会按密度换算显示结果不一致。 解决所有textSize一律使用 sp控件宽高、边距、圆角全部使用 dp。sp 会跟随系统“字体大小”设置变化既能满足用户无障碍放大的需求也不会出现同一套资源在两台机器上差异过大的问题。检查方法很简单在文件中搜索textSize[0-9]dp全部替换成 sp 即可。这里用查找替换能一次性清掉所有问题。6. 落地技巧深色主题与三档尺寸适配让界面源码直接进生产项目6.1 深色模式只需要一套布局但颜色要抽成资源界面源码默认给的都是浅色背景。现在很多应用要求跟随系统深色模式如果为了深色再复制一份布局文件就出现两份 XML 要维护的灾难。正确做法是布局里不写任何颜色值全部引用color/xxx然后单独提供一套深色色值文件。浅色模式的values/colors.xml保留原始配置color namepage_bg#FFFFFF/color color nameinput_bg#F5F6FA/color color nametext_primary#222222/color color namedivider_line#E6E9F0/color新建values-night/colors.xml只写深色版本color namepage_bg#1C1C1E/color color nameinput_bg#2C2C2E/color color nametext_primary#F2F2F2/color color namedivider_line#3A3A3C/color系统在深色模式下会自动加载values-night目录里的同名资源布局文件一行不用改。注意把按钮主色也整理成变量比如color_primary同时用在登录按钮、聚焦边框、协议链接上深色模式下统一调亮度避免深灰背景上出现刺眼的亮蓝。6.2 用 dimens 把页面基准间距拆成三档界面源码在不同屏幕上是否变形核心看间距和字体。源码里如果直接写死了24dp、48dp那我建议改成 dimens 资源按屏幕宽度分档覆盖。最稳妥的做法是以最低支持设备宽度为基准再拉高到资源限定目录。在values/dimens.xml写基准值dimen namepage_margin16dp/dimen dimen nametouch_target_height48dp/dimen dimen nameinput_text_size16sp/dimen在values-sw360dp/dimens.xml写稍宽屏幕的值dimen namepage_margin24dp/dimen在values-sw400dp/dimens.xml写平板或大屏手机的值dimen namepage_margin32dp/dimen dimen nametouch_target_height52dp/dimenswXXXdp表示屏幕最短边的最小宽度系统会加载符合条件的目录。之后布局里全部引用dimen/page_margin挤压屏幕时用 16dp 边距宽屏用 32dp输入框高度也可以和大屏设备同步调大。这个改动只影响尺寸不影响控件结构比写死三联布局省事很多。我每次拿到新手发来的界面源码都会先花十分钟做三件事把根布局加上fitsSystemWindows、把按钮背景换成 selector、把硬编码颜色抽到colors.xml。这三步做完源码基本就能干净地接进正式工程。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?