当前位置:  编程技术>移动开发
本页文章导读:
    ▪用Core Text创造简单杂志应用(1)        用Core Text创建简单杂志应用(1)原文:http://www.raywenderlich.com/4147/how-to-create-a-simple-magazine-app-with-core-text本文作者Marin Todorov,拥有12年以上的软件开发经历,是一位独立的iOS开发者,同时是TouchC.........
    ▪ IntelliJ IDEA 12 编译时报错:“编码GBK的不可投射字符”,"未结束的字符串字面值"和非法的类型开始        IntelliJ IDEA 12 编译时报错:“编码GBK的不可映射字符”,"未结束的字符串字面值"和非法的类型开始 使用12版本时,导入eclipse的代码会出现如上问题,想了一下应该是编码问题。不罗嗦之间给.........
    ▪ Java-取舍排序,冒泡排序       Java--选择排序,冒泡排序import java.util.*; /* 对给定数组进行排序。 {5,1,6,4,2,8,9} */ class ArrayTest2 { /* 选择排序。 内循环结束一次,最值出现头角标位置上。 */ public static void selectSort(int[] a.........

[1]用Core Text创造简单杂志应用(1)
    来源: 互联网  发布时间: 2014-02-18
用Core Text创建简单杂志应用(1)

原文:http://www.raywenderlich.com/4147/how-to-create-a-simple-magazine-app-with-core-text

本文作者Marin Todorov,拥有12年以上的软件开发经历,是一位独立的iOS开发者,同时是TouchCode 杂志的创建者。


Core Text是iOS 3.2和OSX10.5之后的文本引擎,能够精确控制文本的布局及样式。

它位于UIKit和CoreGraphics/Quartz之间:

  •  使用UIKit,你可以通过简单拖拽将文本显示在UILabel上,但你无法单独控制文本中每个字的颜色。
  • 使用Core Graphics/Quartz,你可以做到系统能够做到的一切,但你需要计算文本每个字符绘制在屏幕上的坐标。
  • Core Text 恰巧位于二者之间。你能完全控制文字的位置、布局以及颜色大小等属性,但Core Text也为你省去了一些工作——例如从文本换行到字体的渲染。

在创建一个杂志或书刊类的应用时,Core Text尤其便利——而且在iPad上也工作得很好。

本文通过创建一本非常简单的杂志应用教你如何使用CoreText。你将学到:

  • 在屏幕上显示格式文本
  • 精确控制文本的外观
  • 在文本内容中插入图片
  • 最终创建一个杂志应用,并通过标记来控制文本的格式

在阅读本文之前,你需要有一点iOS开发基础。否则,你可以先阅读这个站点的其他教程。

让我们立即开始iPad杂志之旅。

创建 Core Text 项目

打开Xcode,点击 File\New\New Project, 选择 iOS\Application\View-basedApplication, 点击 Next。项目名称命名为 CoreTextMagazine, Device family选择iPad, 点击 Next, 选择项目存放路径,然后点击 Create。

接下来将Core Text框架加到项目中。

Next thing you have to do is add the Core Text framework to theproject:

  • 在 Project  导航面板中选择项目文件 (屏幕左边的导航窗口)
  • 在Targets列表中选择 “CoreTextMagazine”
  • 点击“Build phases” 栏
  • 展开 “Link Binary With Libraries” 并点击 “+” 号按钮
  • 在列表中选择 “CoreText.framework” 然后点击 “Add”按钮
  • 接下来编写一些代码。

    添加一个 Core Text 视图

    为了便于使用Core Text,我们应当创建一个定制的UIView,然后在它的drawRect:方法中使用Core Text。

    打开File\New\New File菜单,选择 iOS\Cocoa Touch\Objective-C class, 点击 Next。选择UIView的子类, 点击 Next, 类名命名为 CTView, 然后点击 Save。

     

    在CTView.h 的 @interface 加入一下代码已包含 Core Text 框架:

    #import <CoreText/CoreText.h>

    接下来,设置新的定制的UIView作为应用程序的主视图。

    在项目导航窗口中选择 “CoreTextMagazineViewController.xib”文件,转到Xcode的 Utilities 工具条,选择第3个按钮即 Identity 栏.

    现在界面编辑器中选择view对象,在Utilities窗口的Class栏,可以看到UIView字样,将它改为 “CTView” 然后回车。

    现在,应用程序启动时将显示定制的Core Text视图了。接下来,我们编写一点代码作为测试。

    打开CTView.m 删除所有方法。输入以下代码,以便在视图中绘制一个内容为 “Hello world” 的文本:

    - (void)drawRect:(CGRect)rect {
         [super drawRect:rect];
         CGContextRef context = UIGraphicsGetCurrentContext();
         CGMutablePathRef path = CGPathCreateMutable(); //1
         CGPathAddRect(path, NULL, self.bounds );
         NSAttributedString* attString = [[[NSAttributedString alloc]         initWithString:@"Hello core text world!"] autorelease]; //2
         CTFramesetterRef framesetter =         CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString); //3
         CTFrameRef frame =         CTFramesetterCreateFrame(framesetter,             CFRangeMake(0, [attString length]), path, NULL); 
         CTFrameDraw(frame, context); //4
         CFRelease(frame); //5
         CFRelease(path);
         CFRelease(framesetter); 
    }

    让我们逐句讨论以上代码(序号和代码后面注释的行号对应):

  • 此句创建了一个路径,用于表示文本将绘制在此区域内。Mac下Core Text支持在各种形状中绘制文本,比如矩形和椭圆。但iOS下仅支持矩形。在本例中,使用整个视图作为文本绘制的路径,直接将self.bounds转变为一个CGPath。
  • 在Coret Text中无法直接使用NSString,而是使用NSAttributedString。NSAttributedString是一个强大的NSString子类,允许你在文本上应用各种格式化属性。待会我们会演示如何使用它,在此我们仅仅是创建一个简单的文本。
  • CTFramesetter是绘制Core Text文本的最重要的一个类。用它来管理所有的字体引用和文本绘制块。现在你需要知道的仅仅是使用 CTFramesetterCreateWithAttributedString函数创建一个 CTFramesetter。在创建出CTFramesetter之后,我们可以用 CTFramesetterCreateFrame 给它指定一个渲染范围(这里我们决定渲染范围为整个字符串),以及绘制文本时文本显示范围,方法最终返回一个文本绘制块。
  • CTFrameDraw在指定上下文中绘制指定的文本绘制块。
  • 最后,释放所用到的对象。
  • 注意,在使用Core text时,请使用一系列函数如 CTFramesetterCreateWithAttributedString 和CTFramesetterCreateFrame 而尽量避免直接使用 Objective-C 对象。

    你可能会奇怪“为什么又要用C,为什么不用Objective-C?”

    这是因为在iOS中的许多低级类库,为了高效和简洁起见,都是用C写的。不必担心,你会发现CoreText函数其实蛮简单的。

    此外,还有一件值得注意的事情:在用“Create”函数创建对象之后,不要忘记同时要用CFRelease函数释放它们。

    无论如何,用Core Text绘制一段简单文本就是这么多了。点击Run,查看运行结果。


    出现了什么问题?就好比许多低级APIs,CoreText使用的是反Y轴坐标系。因此文本内容被渲染成倒立的。我们需要记住一点,如果我们把UIKit和Core Text的绘制方向搞混了,你会得到奇怪的结果。让我们来解决这个问题。在

     “CGContextRef context =UIGraphicsGetCurrentContext();”一行后加入一下代码:

    // Flip the coordinate system
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    代码很简单,仅仅是在当前视图的上下文中应用了一个转换(上下颠倒坐标系)。在每次绘制Core Text的时候复制粘贴这段代码。

    点击Run——庆祝你的第一个CoreText程序吧!


    Core Text 的对象模型

    如果你搞不清什么是 CTFramesetter 和 CTFrame – 那么,我会在这里简单地解释一下Core Text是如何渲染文本内容的。

    Core Text的对象模型如下图所示:

    首先用一个NSAttributedString做为参数创建一个CTFramesetter引用。这将自动创建一个CTTypesetter实例,它管理着你的字体。接下来使用这个CTFramesetter创建一个(或多个)文本块(CTFrame)。CTFrame用于渲染文本。

    在创建文本块时,需要告诉它一个范围(NSRange),指定文本将在某个矩形内进行渲染。Core Text为每行文字自动创建一个CTLine,同时(注意这里)为每个CTLine中的每一段格式相同的文字创建一个CTRun。

    例如,如果在一行中,有几个字是红色,另外几个字是黑色,剩余的字则为粗体,则Core Text将总共为它们创建3个CTRun。特别注意:不需要你来创建CTRun属性,Core Text会基于你提供的NSAttributedString来创建它们。

    每个CTRun对象都采用各自的属性,因此你可以精确地控制诸如字距、连体、字宽、字重等属性。

    创建杂志应用程序

    创建杂志应用程序,我们需要标记出每段文字的属性。我们可以用NSAttributedString的setAttributes:range方法,但未免不够灵活(除非你愿意老老实实地写上成打的代码)。

    更简单地方法,是创建一种简单标记语法的解析器,通过它对杂志内容进行格式化。

    点击File\New\New File, 选择 iOS\Cocoa Touch\Objective-C class, 然后点击Next。选择 NSObject for Subclass of, 点击 Next,为类命名为MarkupParser.m, 然后点击 Save。

    在MarkupParser.h 中删除所有代码,编辑代码,声明属性和方法如下:

    #import <Foundation/Foundation.h> 
    #import <CoreText/CoreText.h>   
    @interface MarkupParser : NSObject {
         NSString* font;
         UIColor* color;
         UIColor* strokeColor;
         float strokeWidth;
         NSMutableArray* images; 
    }   
    @property (retain, nonatomic) NSString* font; 
    @property (retain, nonatomic) UIColor* color; 
    @property (retain, nonatomic) UIColor* strokeColor; 
    @property (assign, readwrite) float strokeWidth;   
    @property (retain, nonatomic) NSMutableArray* images;   
    -(NSAttributedString*)attrStringFromMarkup:(NSString*)html;   
    @end

    打开MarkupParser.m 将其中内容替换为以下代码:

    #import "MarkupParser.h"   
    @implementation MarkupParser   
    @synthesize font, color, strokeColor, strokeWidth; 
    @synthesize images;   
    -(id)init { 
        self = [super init];  
        if (self) { 
            self.font = @"Arial"; 
            self.color = [UIColor blackColor];  
            self.strokeColor = [UIColor whiteColor]; 
            self.strokeWidth = 0.0;   
            self.images = [NSMutableArray array];     
        }
        return self; 
    }   
    -(NSAttributedString*)attrStringFromMarkup:(NSString*)markup {   }   
    -(void)dealloc {
         self.font = nil;
         self.color = nil;
         self.strokeColor = nil;
         self.images = nil;  
         [super dealloc]; 
    }   
    @end

    如你所见,这个解析器的代码很简单——它包含的属性只有字体、字体颜色、删除线粗细、删除线颜色。后面我们将在文本中使用图片,因此用一个数组来存储这些图片。

    通常写一个解析器不是件轻松的活儿,我将演示的是教你编写一个非常非常简单的解析器(使用正则式)。本教程的解析器非常简单,仅支持开放标签——例如,从一个标签后开始设置文本的样式,一直应用这个样式直到遇到新的标签。就像这段标记语言:

    These are <font color="red">red<font color="black"> and <font color="blue">blue <font color="black">words. 

    将产生如下输出:

    These are red and blue words. 

    对于本文而言,这就足够了。在你自己的项目中,你可以扩展它。

    让我们开始吧!

    在attrStringFromMarkup: 方法中,加入:

    NSMutableAttributedString* aString =
         [[NSMutableAttributedString alloc] initWithString:@""]; //1   
    NSRegularExpression* regex = [[NSRegularExpression alloc]
       initWithPattern:@"(.*?)(<[^>]+>|\\Z)"
               options:NSRegularExpressionCaseInsensitive|
                       NSRegularExpressionDotMatchesLineSeparators
                 error:nil]; //2 
    NSArray* chunks = [regex matchesInString:markup
           options:0
             range:NSMakeRange(0, [markup length])];
    [regex release];

    以上代码分为两步:

  • 首先,声明一个空字符串的NSMutableAttributeString用于结果的返回,后面我们会加入搜索到的匹配的字符串。
  • 接下来,创建一个正则表达式,用于匹配文本和标记。该正则表达式用于匹配一段文字以及其后的标记。该正则表达式的意思是“查找一系列字符,一直到遇到一个以左尖括号开始、右尖括号结束的任意个字符。如果遇到字符串结束则停止处理”。.
  • 为什么要创建这个正则表达式?我们用它来搜索字符串中每个匹配的位置,然后:

    1)渲染所找到的文本部分;

    2)根据所找到标签改变当前样式。

    整个过程重复进行,直至文本结束。

    确实很简单,不是吗?




        
    [2] IntelliJ IDEA 12 编译时报错:“编码GBK的不可投射字符”,"未结束的字符串字面值"和非法的类型开始
        来源: 互联网  发布时间: 2014-02-18
    IntelliJ IDEA 12 编译时报错:“编码GBK的不可映射字符”,"未结束的字符串字面值"和非法的类型开始

    使用12版本时,导入eclipse的代码会出现如上问题,想了一下应该是编码问题。不罗嗦之间给出解决流程:

    Setting->File Encodings->IDE Encoding选择utf-8,不要选择“system default” 
    同时,Default encoding for properties files 也选择 UTF-8



        
    [3] Java-取舍排序,冒泡排序
        来源: 互联网  发布时间: 2014-02-18
    Java--选择排序,冒泡排序
    import java.util.*;
    /*
    对给定数组进行排序。
    {5,1,6,4,2,8,9}
    
    
    */
    class ArrayTest2 
    {
    
    	/*
    	选择排序。
    	内循环结束一次,最值出现头角标位置上。
    	*/
    	public static void selectSort(int[] arr)
    	{
    		for (int x=0; x<arr.length-1 ; x++)
    		{
    			for(int y=x+1; y<arr.length; y++)
    			{
    				if(arr[x]>arr[y])
    				{
    					/*
    					int temp = arr[x];
    					arr[x] = arr[y];
    					arr[y]= temp;
    					*/
    					swap(arr,x,y);
    				}
    			}
    		}
    	}
    	/*
    	冒泡排序
    	*/
    
    	public static void bubbleSort(int[] arr)
    	{
    		for(int x=0; x<arr.length-1; x++)
    		{									
    			for(int y=0; y<arr.length-x-1; y++)//-x:让每一次比较的元素减少,-1:避免角标越界。
    			{
    				if(arr[y]<arr[y+1])
    				{
    					/*
    					int temp = arr[y];
    					arr[y] = arr[y+1];
    					arr[y+1] = temp;
    					*/
    					swap(arr,y,y+1);
    				}
    			}
    		}
    	}
    
    	/*
    	发现无论什么排序。都需要对满足条件的元素进行位置置换。
    	所以可以把这部分相同的代码提取出来,单独封装成一个函数。
    	*/
    	public static void swap(int[] arr,int a,int b)
    	{
    		int temp = arr[a];
    		arr[a] = arr[b];
    		arr[b] = temp;
    	}
    	public static void main(String[] args)
    	{
    		int[] arr = {5,1,6,4,2,8,9};
    		//排序前;
    		printArray(arr);
    
    		//排序
    		//selectSort(arr);
    		//bubbleSort(arr);
    
    		//Arrays.sort(arr);//java中已经定义好的一种排序方式。开发中,对数组排序。要使用该句代码。
    		//排序后:
    		printArray(arr);
    			
    	}
    
    	public static void printArray(int[] arr)
    	{
    		System.out.print("[");
    		for(int x=0; x<arr.length; x++)
    		{
    			if(x!=arr.length-1)
    				System.out.print(arr[x]+", ");
    			else
    				System.out.println(arr[x]+"]");
    
    		}		
    	}
    }
    


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3