Spans进阶
2015-07-30 15:36
423 查看
Spans进阶
原文:Spans, a Powerful Concept.转载:http://zhengxiaopeng.com/的博客,博主翻译辛苦了。
最近,我写了一篇关于NewStand app和app上ActionBar的图标的翻转动效的文章。Cyril Mottier建议我采用一个很优雅的方案,即使用Spans去淡入淡出ActionBar的标题。
此外,我一直想尝试所有可用的Sapn色的类型:ImageSpan、BackgroundColorSpan等。他们非常简单易用但是(也)没有任何关于它们的文档和详细信息。
因此,在这篇文章中,我将探索在Spans的框架下什么是可以做的,然后,我将会告诉你怎么去进阶使用Spans。
你可以下载和安装demo程序,查看源码(再次感谢博主)。
框架
层次
主要规则:如果一个Span影响字符级的文本格式,则继承CharacterStyle。
如果一个Span影响段落层次的文本格式,则实现ParagraphStyle
如果一个Span修改字符级别的文本外观,则实现UpdateAppearance
如果一个Span修改字符级文本度量|大小,则实现UpdateLayout
它为我们提供了下面这些美丽的类图:
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-1.png?imageView2/2/w/850/h/600/q/100)
characterstyle
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-2.png?imageView2/2/w/850/h/600/q/100)
paragraphstyle
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-3.png?imageView2/2/w/850/h/600/q/100)
updateappearance
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-4.png)
updatelayout
因为它有一点复杂所以我建议你使用像这样的可视化类图,以充分理解它的层次结构。
它是如何工作的?
布局(Layout)
当你给一个TextView设置文本时,它使用基类布局去管理文本的渲染。布局类包含一个布尔
mSpannedText:真,当文本是一个Spanned的实例时(SpannableString实现Spanned)。这个类只处理ParagraphStyle Spans。
draw方法调用了其它两个方法:
drawBackground
对于文本的每一行,如果有一个LineBackgroundSpan用于当前行,LineBackgroundSpan#drawBackground)方法将被调用。
drawText
对于文本的每一行,它计算LeadingMarginSpan和LeadingMarginSpan2,并调用LeadingMarginSpan#drawLeadingMargin)方法当它是必要的时候。这也用于确定文本对齐。最后,如果当前行是跨行的,布局将调用
TextLine#draw方法(每一行都会创建一个TextLine对象)。
文本行(TextLine)
android.text.TextLine的文档这么说:代表一行样式的文字,用于测量视觉顺序和为了渲染。TextLine类包含3个Spans的集合:
MetricAffectingSpan set
CharacterStyle set
ReplacementSpan set
其中有趣的方法:TextLine#handleRun,这也是所有的Spans用来渲染文本的。相对于Span的类型,TextLine调用:
CharacterStyle#updateDrawState方法更改MetricAffectingSpan和CharacterStyle两个Spans的TextPaint配置。
TextLine#handleReplacement方法处理ReplacementSpan。它调用Replacement#getSize)得到replacement的宽度,如果它需要更新字体规格最终会调用Replacement#draw
字体规格(Font Metrics)
如果你想知道更多什么是字体规格,那么看下面的图解:![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-5.png)
fontmetrics
耍起来
BulletSpan
android.text.style.BulletSpanBulletSpan影响段落层次的文本格式。它可以给段落的开始处加上项目符号。
1 2 3 4 5 6 7 | /** * gapWidth:项目符号和文本之间的间隙 * color: 项目符号的颜色,默认为透明 */ //创建一个黑色的BulletSpan,间隙为15px span = new BulletSpan(15, Color.BLACK); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-6.png?imageView2/2/w/400/h/300/q/100)
BulletSpan的效果
QuoteSpan
android.text.style.QuoteSpanQuoteSpan影响段落层次的文本格式。它可以给一个段落加上垂直的引用线。
1 2 3 4 5 6 | /** * color: 垂直的引用线颜色,默认是蓝色 */ //创建一个红色的引用 span = new QuoteSpan(Color.RED); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-7.png?imageView2/2/w/400/h/300/q/100)
QuoteSpan的效果
AlignmentSpan.Standard
android.text.style.AlignmentSpan.StandardAlignmentSpan.Standard影响段落层次的文本格式。它可以把段落的每一行文本按正常、居中、相反的方式对齐。
1 2 3 4 5 6 | /** * align: 对齐方式 */ //居中对齐的段落 span = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-8.png?imageView2/2/w/400/h/300/q/100)
AlignmentSpan.Standard的效果
UnderlineSpan
android.text.style.UnderlineSpanUnderlineSpan影响字符级的文本格式。它可以为字符集加上下划线,归功于Paint#setUnderlineText(true))。
1 2 | //下划线 span = new UnderlineSpan(); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-9.png?imageView2/2/w/400/h/300/q/100)
UnderlineSpan效果图
StrikethroughSpan
android.text.style.StrikethroughSpanStrikethroughSpan影响字符级的文本格式。它可以给字符集加上删除线,归功于Paint#setStrikeThruText(true))。
1 2 | //删除线 span = new StrikethroughSpan(); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-10.png?imageView2/2/w/400/h/300/q/100)
StrikethroughSpan的效果图
SubscriptSpan
android.text.style.SubscriptSpanSubscriptSpan影响字符级的文本格式,它可以通过减小TextPaint#baselineShift给字符集加下标。
1 2 | //下标 span = new SubscriptSpan(); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-11.png?imageView2/2/w/400/h/300/q/100)
SubscriptSpan的效果图
SuperscriptSpan
android.text.style.SuperscriptSpanSuperscriptSpan影响字符级的文本格式。它可以通过增加TextPaint#baselineShift 给字符集加上标。
1 2 | //上标 span = new SuperscriptSpan(); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-12.png?imageView2/2/w/400/h/300/q/100)
SuperscriptSpan效果图
BackgroundColorSpan
android.text.style.BackgroundColorSpanBackgroundColorSpan影响字符级的文本格式。它可以给字符集加上背景颜色。
1 2 3 4 5 6 | /** * color: 背景颜色 */ //设置字符背景颜色 span = new BackgroundColorSpan(Color.GREEN); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-13.png?imageView2/2/w/400/h/300/q/100)
BackgroundColorSpan的效果图
ForegroundColorSpan
android.text.style.ForegroundColorSpanForegroundColorSpan影响字符级的文本格式,它可以设置字符集的前景颜色也即文字颜色。
1 2 3 4 5 6 | /** * color: 前景颜色 */ //设置红色的前景 span = new ForegroundColorSpan(Color.RED); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-14.png?imageView2/2/w/400/h/300/q/100)
ForegroundColorSpan的效果图
ImageSpan
android.text.style.ImageSpanImageSpan影响字符级的文本格式。它可以生成图像字符。这是为数不多的文档齐全的Span所以enjoy it!
1 2 3 4 5 6 7 | /** * Context: 上下文 * resourceId: 图像资源id */ //用一个小图像代替字符 span = new ImageSpan(this, R.drawable.pic1_small); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-15.png?imageView2/2/w/400/h/300/q/100)
ImageSpan的效果图
StyleSpan
android.text.style.StyleSpanStyleSpan影响字符级的文本格式,它可以给字符集设置样式(blod、italic、normal)。
1 2 | //设置bold+italic的字符样式 span = new StyleSpan(Typeface.BOLD | Typeface.ITALIC); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-16.png?imageView2/2/w/400/h/300/q/100)
StyleSpan的效果图
TypefaceSpan
android.text.style.TypefaceSpanTypefaceSpan影响字符级的文本格式。它可以给字符设置字体集(monospace、serif等)。
1 2 | //设置serif family span = new TypefaceSpan("serif"); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-17.png?imageView2/2/w/400/h/300/q/100)
TypefaceSpan的效果图
TextAppearanceSpan
android.text.style.TextAppearanceSpanTextAppearanceSpan影响字符级的文本格式。它可以给字符集设置外观(appearance)。
1 2 3 4 5 6 78 | /** * TextAppearanceSpan(Context context, int appearance, int colorList) * context: 上下文 * appearance:appearance资源id(例如:android.R.style.TextAppearance_Small) * colorList:文本的颜色资源id(例如:android.R.styleable.Theme_textColorPrimary) * * TextAppearanceSpan(String family, int style, int size, ColorStateList color, ColorStateList linkColor) * family:字体family * style:描述样式(例如:android.graphics.Typeface) * size:文字大小 * color:文字颜色 * linkColor:连接文本的颜色 */ //设置serif family span = new TextAppearanceSpan(this/*a context*/, R.style.SpecialTextAppearance); |
1 2 3 4 5 6 78 | <-- style.xml --> <style name="SpecialTextAppearance" parent="@android:style/TextAppearance"> <item name="android:textColor">@color/color1</item> <item name="android:textColorHighlight">@color/color2</item> <item name="android:textColorHint">@color/color3</item> <item name="android:textColorLink">@color/color4</item> <item name="android:textSize">28sp</item> <item name="android:textStyle">italic</item> </style> |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-18.png?imageView2/2/w/400/h/300/q/100)
TextAppearanceSpan效果图
AbsoluteSizeSpan
android.text.style.AbsoluteSizeSpanAbsoluteSizeSpan影响字符级的文本格式。它可以设置一个字符集的绝对文字大小。
1 2 3 4 5 6 7 | /** * size: 大小 * dip: false,size单位为px,true,size单位为dip(默认为false)。 */ //设置文字大小为24dp span = new AbsoluteSizeSpan(24, true); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-19.png?imageView2/2/w/400/h/300/q/100)
AbsoluteSizeSpan的效果图
RelativeSizeSpan
android.text.style.RelativeSizeSpanRelativeSizeSpan影响字符水平的文本格式。它可以设置字符集的文本大小。
1 2 | //设置文字大小为大2倍 span = new RelativeSizeSpan(2.0f); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-20.png?imageView2/2/w/400/h/300/q/100)
RelativeSizeSpan的效果图
ScaleXSpan
android.text.style.ScaleXSpanScaleXSpan印象字符集的文本格式。它可以在x轴方向上缩放字符集。
1 2 | //设置水平方向上放大3倍 span = new ScaleXSpan(3.0f); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-21.png?imageView2/2/w/400/h/300/q/100)
ScaleXSpan的效果图
MaskFilterSpan
android.text.style.MaskFilterSpanMaskFilterSpan影响字符集文本格式。它可以给字符集设置android.graphics.MaskFilter。
警告:BlurMaskFilter不支持硬件加速
1 23 | //模糊字符集 span = new MaskFilterSpan(new BlurMaskFilter(density*2, BlurMaskFilter.Blur.NORMAL)); //浮雕字符集 span = new MaskFilterSpan(new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f)); |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-22.png?imageView2/2/w/400/h/300/q/100)
MaskFilterSpan的效果图:
BlurMaskFilter
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-23.png?imageView2/2/w/400/h/300/q/100)
MaskFilterSpan的效果图:
EmbossMaskFilter
Spans进阶
前景色(文字颜色)动画
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-24.gif?imageView2/2/w/400/h/300/q/100)
前景色(文字颜色)动画
ForegroundColorSpan为只读。这意味实例化之后着你不能改变你不能改变前景色。所以,要做的第一件事就是编写一个MutableForegroundColorSpan。
MutableForegroundColorSpan.java
1 2 3 4 5 6 78 | public class MutableForegroundColorSpan extends ForegroundColorSpan { private int mAlpha = 255; private int mForegroundColor; public MutableForegroundColorSpan(int alpha, int color) { super(color); mAlpha = alpha; mForegroundColor = color; } public MutableForegroundColorSpan(Parcel src) { super(src); mForegroundColor = src.readInt(); mAlpha = src.readInt(); } public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(mForegroundColor); dest.writeFloat(mAlpha); } @Override public void updateDrawState(TextPaint ds) { ds.setColor(getForegroundColor()); } /** * @param alpha from 0 to 255 */ public void setAlpha(int alpha) { mAlpha = alpha; } public void setForegroundColor(int foregroundColor) { mForegroundColor = foregroundColor; } public float getAlpha() { return mAlpha; } @Override public int getForegroundColor() { return Color.argb(mAlpha, Color.red(mForegroundColor), Color.green(mForegroundColor), Color.blue(mForegroundColor)); } } |
1 2 3 4 5 6 78 | MutableForegroundColorSpan span = new MutableForegroundColorSpan(255, Color.BLACK); spannableString.setSpan(span, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(spannableString); //黑色完全不透明(译者注:上面代码的效果) span.setAlpha(100); span.setForegroundColor(Color.RED); //到这一步文字没有变化 textView.setText(spannableString); //最后,文字变为红色和透明 |
1 2 3 4 5 6 78 | private static final Property<MutableForegroundColorSpan, Integer> MUTABLE_FOREGROUND_COLOR_SPAN_FC_PROPERTY = new Property<MutableForegroundColorSpan, Integer>(Integer.class, "MUTABLE_FOREGROUND_COLOR_SPAN_FC_PROPERTY") { @Override public void set(MutableForegroundColorSpan span, Integer value) { span.setForegroundColor(value); } @Override public Integer get(MutableForegroundColorSpan span) { return span.getForegroundColor(); } }; |
1 2 3 4 5 6 78 | MutableForegroundColorSpan span = new MutableForegroundColorSpan(255, Color.BLACK); mSpannableString.setSpan(span, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ObjectAnimator objectAnimator = ObjectAnimator.ofInt(span, MUTABLE_FOREGROUND_COLOR_SPAN_FC_PROPERTY, Color.BLACK, Color.RED); objectAnimator.setEvaluator(new ArgbEvaluator()); objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //refresh mText.setText(mSpannableString); } }); objectAnimator.start(); |
ActionBar”烟火”
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-25.gif?imageView2/2/w/400/h/200/q/100)
ActionBar"烟火"
“烟火”动画是让文字随机淡入。首先,把文字切断成多个spans(例如,一个character的span),淡入spans后再淡入其它的spans。用前面介绍的MutableForegroundColorSpan,我们将创建一组特殊的span对象。在span组调用对应的setAlpha方法,我们随机设置每个span的透明度。
1 2 3 4 5 6 78 | private static final class FireworksSpanGroup { private final float mAlpha; private final ArrayList<MutableForegroundColorSpan> mSpans; private FireworksSpanGroup(float alpha) { mAlpha = alpha; mSpans = new ArrayList<MutableForegroundColorSpan>(); } public void addSpan(MutableForegroundColorSpan span) { span.setAlpha((int) (mAlpha * 255)); mSpans.add(span); } public void init() { Collections.shuffle(mSpans); } public void setAlpha(float alpha) { int size = mSpans.size(); float total = 1.0f * size * alpha; for(int index = 0 ; index < size; index++) { MutableForegroundColorSpan span = mSpans.get(index); if(total >= 1.0f) { span.setAlpha(255); total -= 1.0f; } else { span.setAlpha((int) (total * 255)); total = 0.0f; } } } public float getAlpha() { return mAlpha; } } |
1 2 3 4 5 6 78 | private static final Property<FireworksSpanGroup, Float> FIREWORKS_GROUP_PROGRESS_PROPERTY = new Property<FireworksSpanGroup, Float>(Float.class, "FIREWORKS_GROUP_PROGRESS_PROPERTY") { @Override public void set(FireworksSpanGroup spanGroup, Float value) { spanGroup.setProgress(value); } @Override public Float get(FireworksSpanGroup spanGroup) { return spanGroup.getProgress(); } }; |
1 2 3 4 5 6 78 | final FireworksSpanGroup spanGroup = new FireworksSpanGroup(); //初始化包含多个spans的grop //spanGroup.addSpan(span); //给ActionBar的标题设置spans //mActionBarTitleSpannableString.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spanGroup.init(); ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(spanGroup, FIREWORKS_GROUP_PROGRESS_PROPERTY, 0.0f, 1.0f); objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //更新标题 setTitle(mActionBarTitleSpannableString); } }); objectAnimator.start(); |
使用自定义的span
在本节中,我们将看到使用自定义span来绘制的方式。这是文本定制很好的方式。首先,我们要创建一个继承ReplacementSpan抽象类的自定义Span。
如果你想画一个自定义的背景,你可以实现LineBackgroundSpan
,这是影响段落级的文本格式。
我们必须实现2个方法:
getSize):这个方法返回新的你更换后的size。
text:Span管理的文本
start:文本开始处
end:文本结尾处
fm:字体规格,可以为空
draw):可以使用Canvas绘制。
x:绘制文本的x坐标
top:线(line)的顶部(译者注:line的定义参看前面字体规格这一节)
y:基线
bottom:线的底部、
让我们看一个例子,画一个包围文本的蓝色矩形。
FrameSpan.java
1 2 3 4 5 6 78 | @Override public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { //将返回相对于Paint画笔的文本 mWidth = (int) paint.measureText(text, start, end); return mWidth; } @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { //使用自定义的画笔绘制在画布上 canvas.drawRect(x, top, x + mWidth, bottom, mPaint); } |
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-24.png?imageView2/2/w/400/h/300/q/100)
自定义Span的效果
附加
Sample app包含了一些Spans进阶的例子,如下:![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-26.gif?imageView2/2/w/400/h/300/q/100)
Progressive
blur
![](http://rocko-blog.qiniudn.com/Spans%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%A6%82%E5%BF%B5-27.gif?imageView2/2/w/400/h/300/q/100)
Typewriter
总结
在编写这篇文章的过程中,我意识到Spans是真的像Drawable那样强大的,我认为它们还没有被充分运用。文本是一个应用程序的主要内容,它无处不在,所以不要忘记,通过Spans让它变得更具活力和吸引力!相关文章推荐
- monkey、monkeyrunner使用方法
- Cocos2d-x TitleMap A*算法实现。(初版)
- Java 正则表达式详解
- 滚动列表时隐藏输入框
- Zynq片内XADC应用笔记
- c语言实现几种排序算法OC实现
- server-u做的FTP服务器客户端访问文件乱码的解决办法
- C# Winform 跨线程更新UI控件常用方法总结(转)
- 64. Minimum Path Sum
- hdu 4027 2011上海赛区网络赛G 线段树 成段平方根 ***
- 【C语言探索之旅】 第二部分第十课:练习题和习作
- iOS开发UI篇—UITableviewcell的性能优化和缓存机制
- 个人常用iOS第三方库以及XCode插件介绍
- Win10正式版产品安装密钥发布 升级Win10正式版激活密钥汇总
- monkeyrunner 使用
- autoconf & automake
- 【语言-c++】map的使用
- C++学习笔记(一)
- (easy)LeetCode 205.Reverse Linked List
- 读书笔记MoreEffectiveC++(31)