首页 文章 精选 留言 我的

精选列表

搜索[人设自定义],共10000篇文章
优秀的个人博客,低调大师

新书内容连载(1):自定义Android组件之带图像的TextView

本文为原创,如需转载,请注明作者和出处,谢谢! 本文为新书《Android/OPhone 开发完全讲义》的内容连载。《Android/OPhone开发完全讲义》一书现已出版,敬请关注。 购 买: 互动网 《Android/OPhone 开发完全讲义》目录 源代码下载 在本例中要实现一个可以在文本前方添加一个 图像(可以是任何Android系统支持的图像格式)的TextView组件。在编写代码之前,先看一下Android组件的配置代码。 < TextView android:id ="@+id/textview1" android:layout_width ="fill_parent" android:layout_height ="wrap_content" android:text ="textview1" /> 在构造方法中可以通过AttributeSet接口的相应getter方法来读取指定的属性值,如果 在配置属性时指定了命名空间,需要在使用getter方法获得属性值时指定这个命名空间,如果未指定命名空间,则将命名空间设为null即可。 IconTextView是本例要编写的组件类,该类从TextView继承,在onDraw方法中将TextView中的文本后移,并在文本的前方添加了一个图像,该图像的资源ID通过mobile:iconSrc属性来指定。IconTextView类的代码如下: packagenet.blogjava.mobile.widget; importandroid.content.Context; importandroid.graphics.Bitmap; importandroid.graphics.BitmapFactory; importandroid.graphics.Canvas; importandroid.graphics.Rect; importandroid.util.AttributeSet; importandroid.widget.TextView; public classIconTextView extendsTextView { // 命名空间的值 private finalStringnamespace="http://net.blogjava.mobile"; // 保存图像资源ID的变量 private intresourceId=0; privateBitmapbitmap; publicIconTextView(Contextcontext,AttributeSetattrs) { super(context,attrs); // getAttributeResourceValue方法用来获得组件属性的值,在 本例中需要通过该方法的第1个参数指 // 定命名空间的值。该方法的第2个参数表示组件属性名(不包括命名空间名称),第3个 参数表示默 // 认值,也就是如果该属性不存在,则返回第3个参数指定的值 resourceId=attrs.getAttributeResourceValue(namespace,"iconSrc",0); if(resourceId>0) // 如果成功获得图像资源的ID,装载这个图像资源,并创建Bitmap对象 bitmap=BitmapFactory.decodeResource(getResources(),resourceId); } @Override protected voidonDraw(Canvascanvas) { if(bitmap!= null) { // 从原图上截取图像的区域,在本例中为整个图像 Rectsrc= newRect(); // 将截取的图像复制到bitmap上的目标区域,在本例中与复制区域相同 Recttarget= newRect(); src.left=0; src.top=0; src.right=bitmap.getWidth(); src.bottom=bitmap.getHeight(); inttextHeight=( int)getTextSize(); target.left=0; // 计算图像复制到目标区域的纵坐标。由于TextView组件的文本内容并不是 // 从最顶端开始绘制的,因此,需要重新计算绘制图像的纵坐标 target.top=( int)((getMeasuredHeight()-getTextSize())/2)+1; target.bottom=target.top+textHeight; // 为了保证图像不变形,需要根据图像高度重新计算图像的宽度 target.right=( int)(textHeight*(bitmap.getWidth()/( float)bitmap.getHeight())); // 开始绘制图像 canvas.drawBitmap(bitmap,src,target,getPaint()); // 将TextView中的文本向右移动一定的距离(在本例中移动了图像宽度加2个象素 点的位置) canvas.translate(target.right+2,0); } super.onDraw(canvas); } } 在编写上面代码时需要注意如下3点: 1. 需要指定命名空间的值。该值将在<LinearLayout>标签的xmlns:mobile属性中定义。 2. 如果在配置组件的属性时指定了命名空间,需要在AttributeSet 接口的相应getter方法中的第1个参数指定命名空间的值,而第2个参数只需指定不带命名空间的属性名即可。 3. TextView类中的onDraw方法一定要在translate方法后面执行,否则系统不会移动TextView中的文本。 运行本实例后,将显示如图 1 所示的效果。 注意:虽然很多人认为组件的属性必须以android命名空间开头,该命名空间的值必须是http://schemas.android.com/apk/res/android。实际上,只是命名空间的值必须是http://schemas.android.com/apk/res/android而已,命名空间的名称可以是任何值,如下面的代码所示: <? xmlversion="1.0"encoding="utf-8" ?> <!-- 将android换成了abcd --> < LinearLayout xmlns:abcd ="http://schemas.android.com/apk/res/android" abcd:orientation ="vertical" abcd:layout_width ="fill_parent" abcd:layout_height ="fill_parent" > </ LinearLayout > 下一篇:新书内容连载(2):Android Activity的生命周期 本文转自银河使者博客园博客,原文链接http://www.cnblogs.com/nokiaguy/archive/2010/04/29/1723497.html如需转载请自行联系原作者 银河使者

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

Openstack组件部署 — 将一个自定义 Service 添加到 Keystone

目录 目录 Keystone 认证流程 让 Keystone 为一个新的项目 Service 提供验证功能 最后 Keystone 认证流程 User 使用凭证(username/password) 到 keystone 验证并获得一个临时的 Token 和 Generic catalog(全局目录),临时的 Token 会存储在 keystone-client(cache UUID locally) 和 keystone-backend 中。 User 使用这个临时 Token 发送给 keystone 并获得一个该 User 能访问的 Tenants 列表 User 再跟 keystone 发送一个请求,表明希望访问的 Tenants keystone 就会向 User 发送一个管理这个 Tenants 的 Services 列表和允许访问这个 Tenants 的 Token (Tenants Token) User 会通过这个 Services 和 Generic catalog(全局目录) 映射找到 Services 的 endpoint,并通过 endpoint 找到实际 Services 组件的位置 然后 User 再拿着 Tenant Token 和 endpoint 来访问实际上的 Service 组 Service 组件会拿着这个 User-Tennat Token 对到 keystone 做进一步的验证(Openstack 要保证每一步操作都是安全的) 如果通过了 7. 的验证的话,keystone 会返回一系列的确认信息和附加信息(User 希望操作的内容)给 Services 最后 Services 执行一系列的操作 让 Keystone 为一个新的项目 Service 提供验证功能 在新项目的配置文件中指定使用 Keytone 认证方式 [keystone_authtoken] auth_uri = http://<keystone_service_ip>:5000 project_domain_id = default project_name = service user_domain_id = default password = fanguiju username = <new_service_name> auth_url = http://<keystone_service_ip>:35357 auth_plugin = password 该配置项的意义: Because most OpenStack services must access the Identity Service, you must configure the IP address of the keystone server to be able to access it. You must also configure the admin_tenant_name, admin_user, and admin_password options for each service to work. 简而言之, 就是让每个不同的 Openstack Service 都使用一个特定的注册在 Keystone 中的 User 去访问 Keystone Service 并请求获得验证服务. 并且该配置项还指定了该项目属于的 Project(资源), 也就是早期版本中的 Tenant. 这里设置的是: 该项目属于 Tenant service. 这个在之后我们会使用到. 所以, 我们首先需要为这个新的项目在 Keystone 中注册一个用户. fanguiju@fanguiju:~/devstack$ keystone user-create --name <new_service_name> --pass fanguiju --enabled true fanguiju@fanguiju:~/devstack$ openstack user list +----------------------------------+----------+ | ID | Name | +----------------------------------+----------+ | 135b2cb86962401c82044fd4ca9daae4 | admin | | 40d75aebc9c34978b23081f8c8ca9af5 | <new_service_name> | | 626110b81b2b4509becafc1964121b7f | nova | | 85c6b9fa9127439880276f070c60dad6 | demo | | 887a5e92599847698c1f601d0f337421 | glance | | 9dc44b1518184c2cacecb2d2f9f8b050 | alt_demo | | b340851dd5a24eb39a2383bb3f1ff36c | cinder | +----------------------------------+----------+ 因为新的项目的Service 属于 Tenant service, 所以需要在这个 Tenant 中注册该项目的 Service fanguiju@fanguiju:~/devstack$ openstack service create --name <new_service_name> --description "<new_service_name> Service" recovery +-------------+----------------------------------+ | Field | Value | +-------------+----------------------------------+ | description | <new_service_name> Service | | enabled | True | | id | c22ebcb4cdd24114a2d581ce18cdd0ca | | name | <new_service_name> | | type | recovery | +-------------+----------------------------------+ fanguiju@fanguiju:~/devstack$ openstack service list +----------------------------------+-------------+----------------+ | ID | Name | Type | +----------------------------------+-------------+----------------+ | 1cfc85bed3e84f2b93c5a9b9c293e1ed | cinder | volume | | 348c1b372deb4c3fa817d340b439728b | ec2 | ec2 | | 3fa397c2b5d647389edae03515c64583 | nova | compute | | 41cfab784e6942189c8dc48fbda59c4e | glance | image | | 7b534b13bd024a04b44f6eeee882208a | keystone | identity | | 9b8de3d592054fc9b6b992be056ffd0a | nova_legacy | compute_legacy | | aed90494567e4deababddd494fc33338 | cinderv2 | volumev2 | | c22ebcb4cdd24114a2d581ce18cdd0ca | <new_service_name> | recovery | +----------------------------------+-------------+----------------+ NOTE: Name 是用于显示的标识, 实际在 Servces 之间生效的是 Type . 在 Tenant service 中注册完之后, 还需要创建 endpoint 记录, 让不同项目的 Services 之间可以定位到该新项目的服务 fanguiju@fanguiju:~/devstack$ openstack endpoint create --region RegionOne <new_service_name> --publicurl 'http://<new_service_ip>:8760/v1/$(tenant_id)s' --internalurl 'http://<new_service_ip>:8760/v1/$(tenant_id)s' --adminurl 'http://<new_service_ip>:8760/v1/$(tenant_id)s' +--------------+------------------------------------------+ | Field | Value | +--------------+------------------------------------------+ | adminurl | http://<new_service_ip>:8760/v1/$(tenant_id)s | | id | 3c35ecc67e7444648dd079d5c0562f5b | | internalurl | http://<new_service_ip>:8760/v1/$(tenant_id)s | | publicurl | http://<new_service_ip>:8760/v1/$(tenant_id)s | | region | RegionOne | | service_id | 513308f8e46944ac8baf1c9758062660 | | service_name | <new_service_name> | | service_type | recovery | +--------------+------------------------------------------+ 到目前为止, 其实还没有完成新项目 Service 的添加, 因为现在为止在 Keystone 中新注册的 User 是没有权限访问这个 Tenant 的, 那么自然也无法获取 Tenant 中的 Services 列表. 所以无法为新项目完成验证的功能. 将 User 绑定到 Tenant 和 Role 中 # 先获取 <new_service_id>/<service_id>/<member_id> openstack user list # <new_service_id> keystone tenant-list # <service_id> openstack role list # <member_id> # 将用户绑定到 Relo admin 和 Tenant service 中 keystone user-role-add --user <new_service_id> --role <member_id> --tenant <service_id> keystone user-role-add --user <new_service_id> --role <admin_id> --tenant <service_id> 验证 User 的权限 fanguiju@fanguiju:~/devstack$ source openrc <new_user> service fanguiju@fanguiju:~/devstack$ keystone user-list +----------------------------------+----------+---------+----------------------+ | id | name | enabled | email | +----------------------------------+----------+---------+----------------------+ | 135b2cb86962401c82044fd4ca9daae4 | admin | True | | | 9dc44b1518184c2cacecb2d2f9f8b050 | alt_demo | True | alt_demo@example.com | | b340851dd5a24eb39a2383bb3f1ff36c | cinder | True | | | 85c6b9fa9127439880276f070c60dad6 | demo | True | demo@example.com | | 40d75aebc9c34978b23081f8c8ca9af5 | <new_service_user> | True | | | 887a5e92599847698c1f601d0f337421 | glance | True | | | 626110b81b2b4509becafc1964121b7f | nova | True | | +----------------------------------+----------+---------+----------------------+ 使用 <new_user> 也能够访问完全的 User list, 表示该 User 具有了 admin 的权限. 最后 小结: 1. Openstack Service 需要一个注册在 Keystone 中的 User 来访问 Keystone service 2. Openstack Service 应该属于 Tenant service 中, 属于服务资源. 3. 这个 User 对 Tenant service 应该具有 admin 或者 member 权限, 所以需要将 User/ Tenant service/Role admin 绑定到一起. 4. 为了 Openstack services 之间可以相互访问, 需要在 service 的 URL 注册到 endpoint 中.

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

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文件系统,支持十年生命周期更新。

WebStorm

WebStorm

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

用户登录
用户注册