首页 文章 精选 留言 我的

精选列表

搜索[AGI开发],共10000篇文章
优秀的个人博客,低调大师

Android官方开发文档Training系列课程中文版:布局性能优化之布局复用

原文地址:http://android.xsoftlab.net/training/improving-layouts/reusing-layouts.html 尽管Android提供了种类繁多的常用控件,但是有时你可能希望重用一些比较复杂的布局。如果要重用这些布局,可以使用< include/>标签与< merge/>标签,它们可将一个布局嵌入进另一个布局中。 可重用布局这项功能特别强大,它可以使你创建那些复杂的可重用布局。比方说,可以用来创建一个含有yes和no按钮的容器或者一个含有progressBar及一个文本框的容器。它还意味着程序可以对这些布局进行单独控制。所以,虽然说你可以通过自定义View的方式来实现更为复杂的UI组件,但是重用布局的方法更简便一些。 创建一个可重用的布局 如果你已经知道哪一个布局需要重用,那么就创建一个新的xml文件用来定义这个布局。下面就定义了一个ActionBar的布局文件,众所周知,ActionBar是会在每个Activity中统一出现的: <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width=”match_parent” android:layout_height="wrap_content" android:background="@color/titlebar_bg"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/gafricalogo" /> </FrameLayout> 使用< include/>标签 在希望添加重用布局的布局内,添加< include/>标签。下面的例子就是将上面的布局加入到了当前的布局中: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width=”match_parent” android:layout_height=”match_parent” android:background="@color/app_bg" android:gravity="center_horizontal"> <include layout="@layout/titlebar"/> <TextView android:layout_width=”match_parent” android:layout_height="wrap_content" android:text="@string/hello" android:padding="10dp" /> ... </LinearLayout> 你也可以重写布局的参数,但只仅限于以android:layout_*开头的布局参数。就像下面这样: <include android:id=”@+id/news_title” android:layout_width=”match_parent” android:layout_height=”match_parent” layout=”@layout/title”/> 如果你要重写< include>标签指定布局的布局属性,那么必须重写android:layout_height及android:layout_width这两个属性,以便使其它属性的作用生效。 使用< merge>标签 在将一个布局内嵌进另一个布局时,< merge>标签可以帮助消除冗余的View容器。举个例子,如果你的主布局是一个垂直的LinearLayout,在它的内部含有两个View,并且这两个View需要在多个布局中重用,那么重用这两个View的布局需要有一个root View。然而,使用单独的LinearLayout作为这个root View会导致在一个垂直的LinearLayout中又嵌了一个垂直的LinearLayout。其实这个内嵌的LinearLayout并不是我们真正想要的,此外它还会降低UI性能。 为了避免出现这种冗杂的View容器,你可以使用< merge>标签作为这两个View的root View: <merge xmlns:android="http://schemas.android.com/apk/res/android"> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/add"/> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/delete"/> </merge> 那么现在再使用这个布局的时候,系统会自动忽略< merge>标签,并会将两个Button View直接加入到布局< include/>标签所指定的位置。

优秀的个人博客,低调大师

Android官方开发文档Training系列课程中文版:手势处理之拖拽或缩放

原文地址:https://developer.android.com/training/gestures/scale.html 这节课主要学习如何使用触摸手势来拖动、放大屏幕上的对象。 拖动对象 如果你的重点在Android 3.0以上的版本,那么你可以使用内置的拖拽事件监听器View.OnDragListener。 触摸手势最常见的操作就是使用它来拖动屏幕上的对象。下面的代码允许用户拖动屏幕上的图像。要注意以下几点: 在拖动操作中,APP会一直保持手指拖动的轨迹,就算是另一只手指触到屏幕也是。举个例子,想象一根手指在拖动着一张图像,这时用户将第二根手指放置到屏幕上,如果APP只是追踪单根手指的轨迹,那么它会将第二根手指作为默认位置,并会将图像移动到这个位置。 为了防止这样的事件发生,APP需要区分第一根手指与其它手指。为此,需要追踪 ACTION_POINTER_DOWN 及 ACTION_POINTER_UP 。ACTION_POINTER_DOWN 及 ACTION_POINTER_UP在第二根手指落下或抬起的时候由onTouchEvent()方法传回。 在ACTION_POINTER_UP的情况下,示例提取了这个事件的索引,并确保当前活动的指针不是那个已经不在屏幕上的指针。如果是那个指针的话,那么APP会选择一个不同的指针使其活动并保存它的X及Y的位置。一旦这个值被保存下来,那么APP将会使用正确指针的数据一直计算剩余移动的距离。 下面的代码允许用户在屏幕上拖动对象。它记录了当前活动指针的初始位置,计算了它所位移的距离,并将对象移动到新的位置上。 这里要注意,代码段使用了getActionMasked()方法。你应该一直使用这个方法来接收MotionEvent对象的活动。与getAction()方法不同,getActionMasked()工作于多点触控模式下。它会返回被执行的掩饰活动,不包括指针的索引比特。 // The ‘active pointer’ is the one currently moving our object. private int mActivePointerId = INVALID_POINTER_ID; @Override public boolean onTouchEvent(MotionEvent ev) { // Let the ScaleGestureDetector inspect all events. mScaleDetector.onTouchEvent(ev); final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_DOWN: { final int pointerIndex = MotionEventCompat.getActionIndex(ev); final float x = MotionEventCompat.getX(ev, pointerIndex); final float y = MotionEventCompat.getY(ev, pointerIndex); // Remember where we started (for dragging) mLastTouchX = x; mLastTouchY = y; // Save the ID of this pointer (for dragging) mActivePointerId = MotionEventCompat.getPointerId(ev, 0); break; } case MotionEvent.ACTION_MOVE: { // Find the index of the active pointer and fetch its position final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float x = MotionEventCompat.getX(ev, pointerIndex); final float y = MotionEventCompat.getY(ev, pointerIndex); // Calculate the distance moved final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; invalidate(); // Remember this touch position for the next move event mLastTouchX = x; mLastTouchY = y; break; } case MotionEvent.ACTION_UP: { mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_CANCEL: { mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_POINTER_UP: { final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) { // This was our active pointer going up. Choose a new // active pointer and adjust accordingly. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex); mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex); mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); } break; } } return true; } 平移 上面的部分展示了如何在屏幕上拖动对象。另一个通用的场景就是平移了,平移的意思是:用户的拖动动作引起的x及y轴方向上的滚动。上面的代码直接将MotionEvent拦截实现拖动。这部分的代码将会采用另一种更具有优势的方法,以便支持通用手势。它重写了GestureDetector.SimpleOnGestureListener的onScroll()方法。 只有用户在使用手指移动内容时,onScroll()才会被调用。onScroll()只有在手指按下的时候才会调用,一旦手指离开屏幕,那么平移手势也随之终止。 下面是onScroll()的使用摘要: // The current viewport. This rectangle represents the currently visible // chart domain and range. private RectF mCurrentViewport = new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX); // The current destination rectangle (in pixel coordinates) into which the // chart data should be drawn. private Rect mContentRect; private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() { ... @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // Scrolling uses math based on the viewport (as opposed to math using pixels). // Pixel offset is the offset in screen pixels, while viewport offset is the // offset within the current viewport. float viewportOffsetX = distanceX * mCurrentViewport.width() / mContentRect.width(); float viewportOffsetY = -distanceY * mCurrentViewport.height() / mContentRect.height(); ... // Updates the viewport, refreshes the display. setViewportBottomLeft( mCurrentViewport.left + viewportOffsetX, mCurrentViewport.bottom + viewportOffsetY); ... return true; } 下面是setViewportBottomLeft()方法的实现,它主要实现了移动内容的逻辑: /** * Sets the current viewport (defined by mCurrentViewport) to the given * X and Y positions. Note that the Y value represents the topmost pixel position, * and thus the bottom of the mCurrentViewport rectangle. */ private void setViewportBottomLeft(float x, float y) { /* * Constrains within the scroll range. The scroll range is simply the viewport * extremes (AXIS_X_MAX, etc.) minus the viewport size. For example, if the * extremes were 0 and 10, and the viewport size was 2, the scroll range would * be 0 to 8. */ float curWidth = mCurrentViewport.width(); float curHeight = mCurrentViewport.height(); x = Math.max(AXIS_X_MIN, Math.min(x, AXIS_X_MAX - curWidth)); y = Math.max(AXIS_Y_MIN + curHeight, Math.min(y, AXIS_Y_MAX)); mCurrentViewport.set(x, y - curHeight, x + curWidth, y); // Invalidates the View to update the display. ViewCompat.postInvalidateOnAnimation(this); } 缩放 在Detecting Common Gestures中,我们讨论到GestureDetector可以帮助我们来检测比如滑动、滚动、长按等手势。而对于缩放,Android提供了ScaleGestureDetector. GestureDetector 以及 ScaleGestureDetector。 为了可以反馈检测到的手势事件,手势探测器使用了监听器对象ScaleGestureDetector.OnScaleGestureListener。如果你只关心部分手势的话,Android还提供了ScaleGestureDetector.SimpleOnScaleGestureListener,你可以通过重写它的方法来使用。 缩放基础示例 下面的代码是缩放所需要的基础: private ScaleGestureDetector mScaleDetector; private float mScaleFactor = 1.f; public MyCustomView(Context mContext){ ... // View code goes here ... mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); } @Override public boolean onTouchEvent(MotionEvent ev) { // Let the ScaleGestureDetector inspect all events. mScaleDetector.onTouchEvent(ev); return true; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.scale(mScaleFactor, mScaleFactor); ... // onDraw() code goes here ... canvas.restore(); } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); // Don't let the object get too small or too large. mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); invalidate(); return true; } } 稍微复杂点的示例 下面是一个稍微复杂一点的示例,它摘自与这节课所提供的示例InteractiveChart(PS:示例工程请参见原网页)。InteractiveChart同时支持平移、缩放,它使用了ScaleGestureDetector的“平移”(getCurrentSpanX/Y)及“焦点” (getFocusX/Y)特性: @Override private RectF mCurrentViewport = new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX); private Rect mContentRect; private ScaleGestureDetector mScaleGestureDetector; ... public boolean onTouchEvent(MotionEvent event) { boolean retVal = mScaleGestureDetector.onTouchEvent(event); retVal = mGestureDetector.onTouchEvent(event) || retVal; return retVal || super.onTouchEvent(event); } /** * The scale listener, used for handling multi-finger scale gestures. */ private final ScaleGestureDetector.OnScaleGestureListener mScaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() { /** * This is the active focal point in terms of the viewport. Could be a local * variable but kept here to minimize per-frame allocations. */ private PointF viewportFocus = new PointF(); private float lastSpanX; private float lastSpanY; // Detects that new pointers are going down. @Override public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) { lastSpanX = ScaleGestureDetectorCompat. getCurrentSpanX(scaleGestureDetector); lastSpanY = ScaleGestureDetectorCompat. getCurrentSpanY(scaleGestureDetector); return true; } @Override public boolean onScale(ScaleGestureDetector scaleGestureDetector) { float spanX = ScaleGestureDetectorCompat. getCurrentSpanX(scaleGestureDetector); float spanY = ScaleGestureDetectorCompat. getCurrentSpanY(scaleGestureDetector); float newWidth = lastSpanX / spanX * mCurrentViewport.width(); float newHeight = lastSpanY / spanY * mCurrentViewport.height(); float focusX = scaleGestureDetector.getFocusX(); float focusY = scaleGestureDetector.getFocusY(); // Makes sure that the chart point is within the chart region. // See the sample for the implementation of hitTest(). hitTest(scaleGestureDetector.getFocusX(), scaleGestureDetector.getFocusY(), viewportFocus); mCurrentViewport.set( viewportFocus.x - newWidth * (focusX - mContentRect.left) / mContentRect.width(), viewportFocus.y - newHeight * (mContentRect.bottom - focusY) / mContentRect.height(), 0, 0); mCurrentViewport.right = mCurrentViewport.left + newWidth; mCurrentViewport.bottom = mCurrentViewport.top + newHeight; ... // Invalidates the View to update the display. ViewCompat.postInvalidateOnAnimation(InteractiveLineGraphView.this); lastSpanX = spanX; lastSpanY = spanY; return true; } };

优秀的个人博客,低调大师

风控开发指南:PHP集成活体识别V步骤1实现精准合规审查

在在线职业资格认证考试、企业内训定级考核及远程技能测评平台中,确保“应试考生确系报名本人且处于真实物理摄像头前”是维护考试公平性与证书公信力的核心前提。传统的远程监考系统多依赖考生在开考前上传静态近期免冠照,或由监考老师通过多人视频会议室逐一人工核对准考证。在数千人同时开考的并发高峰期,人工视频核验不仅耗时长、容易造成考场开考延误,而且静态照片与普通视频流也难以有效识别预录视频重放或虚拟摄像头流注入等非真实应试行为。

优秀的个人博客,低调大师

风控开发指南:Go集成活体识别V步骤1实现精准合规审查

在秀场直播、语音连麦、游戏陪玩及带货公会等泛娱乐直播平台中,每晚黄金档(19:00–22:00)往往有成千上万名签约主播同时发起推流开播或申请高额打赏提现。根据网络视听与直播行业的实名制合规监管要求,平台不仅需要在主播首次签约时完成身份登记,还必须在每次开播推流前确认当前镜头前的主播与实名备案主体一致,防范他人借用高粉账号开播、未成年人冒用亲属账号或利用虚拟摄像头推流等非真实日常账号的履约隐患。传统仅依赖首次上传静态证件照或人工巡查直播间的模式,不仅响应滞后,且难以应对晚高峰瞬时数千 QPS 的开播鉴权并发压力。

优秀的个人博客,低调大师

风控开发指南:Java集成活体识别V步骤1实现精准合规审查

在城商行手机银行 App、微信端 H5 轻网银以及对公移动财资系统的日常交易流转中,客户发起跨行大额转账、单日累计超限额汇款或异地非常用设备动账时,交易发起人真实在场意愿的合规确认是账户资金安全的核心防线。传统的短信验证码(SMS OTP)配合静态交易密码模式,仅能验证介质持有性而无法确认操作者本人的实时生物特征;而早期的柜面视频连线座席人工核身不仅排队耗时长、人力运维成本高,且在夜间或节假日跨行汇款高峰期极易形成服务瓶颈,影响储户与企业财务人员的资金周转体验。

优秀的个人博客,低调大师

风控开发指南:Python集成活体识别V步骤1实现精准合规审查

在远程在线公证、房产委托代办以及电子遗嘱存证平台的司法合规实践中,确认申请人系“本人真实在场且处于实时自然交互状态”是证据链具备法律效力的核心前提。传统的线上公证辅助核验往往要求当事人自行录制手持证件朗读声明的视频并上传后台,再由公证员逐帧人工审阅画面连贯性与口型匹配度。这种作业方式不仅耗费大量司法辅助人力、跨地域签署等待周期漫长,而且异步上传的静态视频文件缺乏实时环境光交互与防重放令牌约束,难以在采集源头排除非实时画面注入等合规隐患,给后续公证文书出具与司法存证带来显著的履约风险。

优秀的个人博客,低调大师

风控开发指南:Go集成人车核验加强版实现精准合规审查

在同城急送、生鲜冷链即时配送以及大件货运等即时物流平台中,海量众包骑手(普通摩托车、轻便摩托车)与带车加盟司机(小型蓝牌面包车、新能源绿牌货运车、黄牌大型货车)的准入合规审查,是保障平台运力安全与履约质量的第一道防线。每逢电商大促或节假日运力招募高峰期,瞬时涌入的司机注册申请往往达到数千 QPS。传统依赖运营人员肉眼比对驾驶员身份证与机动车行驶证 OCR 照片的作业模式,不仅审核链路冗长、人力成本高昂,而且难以在毫秒级时间内识别人车权属脱节、车辆过户未更新或信息不匹配资质等潜在履约隐患。

优秀的个人博客,低调大师

风控开发指南:Java集成人车核验加强版实现精准合规审查

在财产险核心承保系统(特别是干线物流重卡、城配冷链车队、牵引挂车等商用车险种)的日常运转中,投保人或被保险人与机动车行驶证登记所有人的一致性确认,是履行保险利益原则与承保合规审查的核心前提。长期以来,承保前端依赖业务员上传行驶证正副本照片,再结合 OCR 识别与核保作业中心人工复核。然而,商用车作业环境复杂,行驶证塑封反光、油污遮挡或字迹磨损极易导致 OCR 字段提取偏差;而在车辆过户挂靠、车队批量续保等高峰场景下,离线人工审单不仅拉长了出单时效,也难以实时察觉车辆所有权登记状态的最新变更,容易引发后续理赔阶段的权属争议与履约隐患。

优秀的个人博客,低调大师

风控开发指南:PHP集成人车核验加强版实现精准合规审查

在高端商业综合体与写字楼配建住宅的智慧停车管理系统中,业主专属包月停车卡(月卡/产权车位绑定)与临停商业车位往往存在显著的资费差异与潮汐调度优先级。为了保障业主停车权益、防范非业主社会车辆违规占用住宅包月配额,物业管理后台(Property CMS)在开通月卡时必须确认申请人姓名与申报车牌号的真实所有权归属关系。传统的物业审核流程通常依赖车主在小程序端上传纸质行驶证照片与房产证明,再由物业客服人员在后台逐一人工肉眼比对。这种模式不仅在月底集中续费或新盘交付高峰期造成工单积压,还会因照片反光、翻拍模糊或信息滞后带来审核偏差。

优秀的个人博客,低调大师

风控开发指南:Python集成人车核验加强版实现精准合规审查

在干线物流与数字货运撮合平台的日常运营中,个体货车司机携车入驻是运力池构建的核心环节。受限于货运车辆跨省流转频繁、挂靠经营与个体自营并存等行业特性,平台在承运人注册、大宗高价值货物派单以及运费结算签约阶段,均需对司机身份信息与承运车辆所有权的一致性进行严格核查。传统的运力准入流程往往依赖司机上传纸质行驶证照片与驾驶证影像,再由运营审核团队通过 OCR 识别结合人工肉眼比对车主姓名与车牌号码。这种方式不仅审核链路冗长、高峰期运力积压严重,而且静态图片难以实时反映车辆过户变更、号牌种类误报等动态信息偏差,容易在后续运输履约与税务合规开票环节埋下履约隐患。

资源下载

更多资源
Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册