draw9patch怎么用使用draw-9 panth

9.view 作图过程,讲讲draw/onDraw和drawChild - 移动开发当前位置:& &&&9.view 作图过程,讲讲draw/onDraw和drawChild9.view 作图过程,讲讲draw/onDraw和drawChild&&网友分享于:&&浏览:0次9.view 绘制过程,讲讲draw/onDraw和drawChild
转载请标明出处:&
http://blog.csdn.net/yujun411522/article/details/
本文出自:【yujun411522的博客】
&9.1 view的绘制过程
view的绘制过程在UI中还是非常重要的,view的绘制是从根节点,自上而下的一个过程,主要经历三个过程:
先看performTraversals函数代码,这段代码很长,主要工作可以归结为三个函数:& &
ViewRootImpl.java中performTraversals()
private void perfromTraversals(){
final View host = mV
//1.measure过程
host.measure(childWidthMeasureSpec,childHeightMeasureSpec);
//2.layout过程
host.layout(0,0,host.getMeasureWidth(),host.getMeasureHeight);
//3 draw过程
draw(fullRedrawNeeded);
下面分别来介绍着三个过程:
9.1.1 measure
measure中主要涉及以下几个方法:
public&final&void&measure(int widthMeasureSpec,int heightMeasureSpec)
protected voidonMeasure(int widthMeasureSpec,int heightMeasureSpec)
protected&final&void&setMeasureDimension(int measuredWidht,int measureHeight)
这里先还要介绍一个类:MeasureSpec。引入这个类的主要目的是在android中子view的尺寸还要受到父view的限制。
一个MeasureSpec是一个int 类型,共32b,有两部分组成:高两位是mode,剩下的30位是size
mode中有三种模式:
1&UNSPECIFIED:不受到父view的限制,可以设置为任意值。基本上不用到。
2&EXACTLY:父view中指定子view的大小,不管子view如果设置。比如:match_parent、或者具体的大小
3&AT_MOST:父view中指定子view最多只能这么多。比如:wrap_content
在ViewRootImpl中已经说明了对应关系& &
private int getRootMeasureSpec(int windowSize, int rootDimension) {
int measureS
switch (rootDimension) {
case ViewGroup.LayoutParams.MATCH_PARENT&/strong&:
// Window can't resize. Force root view to be windowSize.
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
case ViewGroup.LayoutParams.WRAP_CONTENT&/strong&:
// Window can resize. Set max size for root view.
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
// Window wants to be an exact size. Force root view to be that size.
measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
return measureS
可以看出match_parent和具体尺寸对应的都是EXACTLY,wrap_content对应的是AT_MOST。
接下来看一下view.measure函数的处理过程& &&
public final void measure (int widthMeasureSpec, int heightMeasureSpec) {
// measure ourselves, this should set the measured dimension flag back
onMeasure(widthMeasureSpec, heightMeasureSpec);
mOldWidthMeasureSpec = widthMeasureS
mOldHeightMeasureSpec = heightMeasureS
调用了onMeasure方法:& &
protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimensiongetDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
里面涉及了三个方法:getSuggestedMinimumWidth,getDefaultSize,setMeasuredDimension
先看view.getSuggestedMinimumWidth()&&
protected int getSuggestedMinimumWidth() {
int suggestedMinWidth = mMinW
if (mBGDrawable != null) {
final int bgMinWidth = mBGDrawable.getMinimumWidth();
if (suggestedMinWidth & bgMinWidth) {
suggestedMinWidth = bgMinW
return suggestedMinWidth&/strong&;//返回背景图最小值和view最小值中的较大者
getSuggestedMinimumHeight()方法类似,不做介绍。
再看view.getDefaultSize()方法&&
public static int getDefaultSize(int size, int measureSpec) {
int result =
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result =//UNSPECIFIED,返回值为size值
case MeasureSpec.AT_MOST://AT_MOST,返回值为size值
case MeasureSpec.EXACTLY:
result = specS//EXACTLY,返回值为specSize值
再看setMeasuredDimension方法:& &&&
protected final void setMeasuredDimension (int measuredWidth, int measuredHeight) {
mMeasuredWidth = measuredW
mMeasuredHeight = measuredH
mPrivateFlags |= MEASURED_DIMENSION_SET ;
我们在override完onMeasure方法之后一定要执行这个setMeasuredDimension方法,这个方法的目的就是保存measure之后的值。
以上介绍的是view的measure过程,如果是viewGroup时流程会有区别:viewGroup循环measure所有子view。先看一看ViewGroup中的measureChildren方法& &
* Ask all of the children of this view to measure themselves, taking into account both the MeasureSpec requirements for this view and its padding.
* We skip children that are in the GONE state The heavy lifting is done in getChildMeasureSpec.
* @param widthMeasureSpec The width requirements for this view
* @param heightMeasureSpec The height requirements for this view
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
final int size = mChildrenC
final View[] children = mC
for (int i = 0; i & ++i) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {//过滤掉GONE的view
measureChild(child, widthMeasureSpec, heightMeasureSpec);//让所有的子view measure自己。调用measureChild方法。
调用ViewGroup.measureChild(view,int,int)。类似measureChild函数还有measureChildWithMargins(view,int,int))
* Ask one of the children of this view to measure itself, taking into account both the MeasureSpec requirements for this view and its padding.
* The heavy lifting is done in getChildMeasureSpec.
* @param child The child to measure
* @param parentWidthMeasureSpec The width requirements for this view
* @param parentHeightMeasureSpec The height requirements for this view
protected void measureChild(View child, int parentWidthMeasureSpec,int parentHeightMeasureSpec) {
final LayoutParams lp = child.getLayoutParams();
//主要工作还是在getChildMeasureSpec函数中进行
final int childWidthMeasureSpec = getChildMeasureSpec&/strong&(parentWidthMeasureSpec,mPaddingLeft+mPaddingRight, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec&/strong&(parentHeightMeasureSpec, mPaddingTop+ mPaddingBottom, lp.height);
child.measure&/strong&(childWidthMeasureSpchildHeightMeasureSpec ec, childHeightMeasureSpec);//计算完childWidthMeasureSpec 、childHeightMeasureSpec 调用子view的measure方法
其中调用了ViewGroup.getChildMeasureSpec方法,这个方法比较复杂:&此方法的目的是根据父view对子view的MeasureSpec和子view的layout参数产生一个最合适的MeasureSpec&&
/ * Does the hard part of measureChildren: figuring out the MeasureSpec to pass to a particular child. This method figures out the right MeasureSpec for one dimension (height or width) of one child view. The goal is to combine information from ourMeasureSpec with the LayoutParams of the child to get the best possible results. For example,if the this view knows its size (because its MeasureSpec has a mode of EXACTLY), and the child has indicated in its LayoutParamsthat it wants to be the same size as the parent, the parent should ask the child to layout given an exact size.
* @param spec The requirements for this view
* @param padding The padding of this view for the current dimension and
margins, if applicable
* @param childDimension How big the child wants to be in the current
* @return a MeasureSpec integer for the child
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
int specMode = MeasureSpec.getMode(spec);
int specSize = MeasureSpec.getSize(spec);
int size = Math.max(0, specSize - padding);
int resultSize = 0;
int resultMode = 0;
switch (specMode) {
// Parent has imposed an exact size on us
case MeasureSpec.EXACTLY:
if (childDimension &= 0) {
resultSize = childD
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size. So be it.
resultSize =
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize =
resultMode = MeasureSpec.AT_MOST;
// Parent has imposed a maximum size on us
case MeasureSpec.AT_MOST:
if (childDimension &= 0) {
// Child wants a specific size... so be it
resultSize = childD
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size, but our size is not fixed.
// Constrain child to not be bigger than us.
resultSize =
resultMode = MeasureSpec.AT_MOST;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize =
resultMode = MeasureSpec.AT_MOST;
// Parent asked to see how big we want to be
case MeasureSpec.UNSPECIFIED:
if (childDimension &= 0) {
// Child wants a specific size... let him have it
resultSize = childD
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size... find out how big it should
resultSize = 0;
resultMode = MeasureSpec.UNSPECIFIED;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size.... find out how
// big it should be
resultSize = 0;
resultMode = MeasureSpec.UNSPECIFIED;
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}可以看出上面的处理过程还是挺复杂的,该方法返回父view对子view的一个32b的measureSpec。
measureChild方法最后调用view的measure方法,再按照view的measure流程绘制。
具体的可以参看不同view控件,以及measure的实现。
9.1.2 layout
measure的过程就是确定view的大小,而layout的过程则是确定view的位置。
看一下view.layout()方法:& &
public void layout(int l, int t, int r, int b) {
int oldL = mL
int oldT = mT
int oldB = mB
int oldR = mR
boolean changed = setFrame(l, t, r, b);
if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED ) {
if (ViewDebug. TRACE_HIERARCHY) {
ViewDebug. trace( this, ViewDebug.HierarchyTraceType.ON_LAYOUT );
onLayout(changed, l, t, r, b);//调用onLayout方法
mPrivateFlags &= ~LAYOUT_REQUIRED ;
if (mOnLayoutChangeListeners != null) {
ArrayList&OnLayoutChangeListener& listenersCopy =
(ArrayList&OnLayoutChangeListener&) mOnLayoutChangeListeners .clone();
int numListeners = listenersCopy.size();
for (int i = 0; i & numL ++i) {
listenersCopy.get(i).onLayoutChange(this , l, t, r, b, oldL, oldT, oldR, oldB);//通知对象的listener调用onLayoutChange
mPrivateFlags &= ~FORCE_LAYOUT ;
调用onLayout方法,再看onLayout方法是一个空实现:&& &
protected void onLayout( boolean changed, int left, int top, int right, int bottom) {
也就是我们需要自己实现onLayout方法。
这是view的layout过程,再看viewGroup过程,先看viewGroup.layout方法:&&
public final void layout(int l, int t, int r, int b) {
if (mTransition == null || !mTransition.isChangingLayout()) {
super.layout&/strong&(l, t, r, b);//调用父类view的layout方法&/strong&
// record the fact that we noop' request layout when transition finishes
mLayoutSuppressed =
调用父类view的layout方法,再看onLayout方法&&
protected abstract void onLayout(boolean changed,int l, int t, int r, int b);
viewGroup.onLayout是抽象函数。
ViewGroup对应的就是一个个具体的布局,看具体布局是如何实现的。
LinearLayout的layoutVertical方法&
void layoutVertical() {
for (int i = 0; i & i++) {
final View child = getVirtualChildAt(i);
if (child == null) {
childTop += measureNullChild(i);
} else if (child.getVisibility() != GONE) {
childTop += lp. topM
setChildFrame&/strong&(child, childLeft, childTop + getLocationOffset(child),
childWidth, childHeight);
childTop += childHeight + lp. bottomMargin + getNextLocationOffset(child);
i += getChildrenSkipCount(child, i);
其中出现了LinearLayout.setChildFrame方法:& &&
private void setChildFrame(View child, int left, int top, int width, int height) {
child.layout(left, top, left + width, top + height);
再看FrameLayout的onLayout方法:&
protected void onLayout( boolean changed, int left, int top, int right, int bottom) {
final int count = getChildCount();
for (int i = 0; i & i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int width = child.getMeasuredWidth();
final int height = child.getMeasuredHeight();
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK ) {
switch (verticalGravity) {
child.layout&/strong&(childLeft, childTop, childLeft + width, childTop + height);
可以看出都是调用子view中的layout方法。所以在自定义view的时候需要自己重写view的onLayout方法。
9.1.3 draw
得到位置之后,最后就是绘制view了。
view做的事情主要有以下几个部分:
1. Draw the background
2. If necessary, save the canvas' layers to prepare for fading
3. Draw view's content
4. Draw children
5. If necessary, draw the fading edges and restore layers
6. Draw decorations (scrollbars for instance)
比较重要的是step3和step4:& & &&
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
其中onDraw实现:空实现。因为view怎样展示是由具体的view自行实现。
protected void onDraw(Canvas canvas) {
// Step 4, draw the children
dispatchDraw(canvas);
里面涉及了两个函数,onDraw和dispatchDraw函数,先看onDraw函数:
protected void onDraw(Canvas canvas) { }//空实现,因为view到底怎么展示是view自己决定的,所以要空实现
再看dispatchDraw方法:
protected void dispatchDraw(Canvas canvas) {
}也是空实现,因为view中没有子view,也就不需要向子view派发draw请求了,所以是空实现。
viewGroup中没有重写draw函数,所以是继承view的draw函数;&
viewGroup中也没有重写onDraw函数,所以是继承view的onDraw函数,也就是空实现
再看viewGroup中的viewGroup.dispatchDraw(Canvas)方法:& & &&
protected void dispatchDraw(Canvas canvas) {
final int count = mChildrenC
final View[] children = mC
int flags = mGroupF
if ((flags & FLAG_USE_CHILD_DRAWING_ORDER) == 0) {
for (int i = 0; i & i++) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
more |= drawChild&/strong&(canvas, child, drawingTime);
for (int i = 0; i & i++) {
final View child = children[getChildDrawingOrder(count, i)];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
more |=drawChild&/strong&(canvas, child, drawingTime);
// Draw any disappearing views that have animations
if (mDisappearingChildren != null) {
final ArrayList&View& disappearingChildren = mDisappearingC
final int disappearingCount = disappearingChildren.size() - 1;
// Go backwards -- we may delete as animations finish
for (int i = disappearingC i &= 0; i--) {
final View child = disappearingChildren.get(i);
more |= drawChild&/strong&(canvas, child, drawingTime);
又调用了drawChild(Canvas,View,Long)方法,此方法主要作用是draw viewGroup中的某一个view,代码太长就不贴出现了。
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 1234567891011 Copyright & &&版权所有关注官方微博有惊喜!
点9切图工具的下载和点9切图使用方式
来源:网络&&&作者:一起学设计小编&&&发布时间:&&&
浏览次数:1533
收藏分享到:
之前,点9图的出现是安卓机为了适配不同的手机分辨率的解决方案。不明白什么是点九的同学可以看这篇文章补一下脑1、普通的.png资源与.9.png的资源区别:关于处理点九图的工具,我想补充说明一下,目前常用的三种方式:第一种:就是使用PS但是其缺点是手工增加四周各1个像素,然后其区域颜色值只能是透明色(#)或黑色(#FF000000),混入其他颜色一律无法正常显示,而且无法实时预览,即使你经验丰富,但也很难去考虑到目前Android市场这么多的机型适配;如果混入了其他颜色,而又未发觉,这样再跟程序员来回折腾,时间上也够喝一壶的了。楼主所说的也属于这一类。第二种:就是使用谷歌官方的draw9Patch.bat这个工具这个也有劣势,1.电脑要安装Java环境,2.下载那个几百M的文件,3.draw9Patch这个工具其实很难用,很粗糙,整个的体验也很糟糕。特别是那一根像素,拖着鼠标仔细的描那根像素,哎呀,别提那个憋屈劲儿了。。。第三种:NinePng九图神器App——Android开发设计必备工具。这是一个专门处理点九图的工具App,能够非常简单的用手指拖动就可以直接修改点九图了,而且可以设置文字等信息实时预览效果。个人感觉还是不错的。APP软件下载官网:详细运用该APP切图的方法和教程地址:最后总结:各位APP设计师们,结合自己的喜爱来使用不同的方式进行点9图处理。特别需要注意以下2点:1.最外围的一圈像素必须要么是纯黑色,要么是透明,一点点的半透明的像素都不可以有,比如说99%的黑色或者是1%的投影都不可以有;2.文件的后缀名必须是.9.png,不能是.png或者是.9.png.png,这样的命名都会导致编译失败。
/UIsheji/lilunjiqiao/2420.htmlAndroid-app(13)
一. .9图片的介绍
.9图片的作用:
1. 主要防止图片被拉伸后变形。因为在一个像素里如果是相同色块,那么它被拉伸不会变形。但如何该像素里有不同色块,就将导致它变形。
2.通过.9图片可以把图片做的很小,不占资源,减少apk的大小
下面我们来看一下,同一张图片使用了.9和不使用.9图片的区别:
由图中,我们可以看出没有使用.9图片的对话框被拉伸的变形了。
我们再看下这俩个背景图片的区别:(左:.9图片 ; 右:非.9图片)
仔细观察,才发现.9图片在左边和上面多了一个小黑点,其他基本一致。 & &
二. .9图片的使用1 -- 拉伸图片
1.上:表示图片被横向拉伸时,黑点所在的区域就是可拉伸的区域
2.左:表示图片被纵向拉伸时,黑点所在的区域就是可拉伸的区域
(关于图片下方和右方的作用在下一个实例中会讲解)
在Draw 9-patch工具中,选中show patches会自动显示出被拉伸的区域。
在Draw 9-patch工具的右手边,可以预览拉伸效果,从上到下依次是:纵向拉伸 / 横向拉伸 / 纵向横向拉伸
下面我们来看一下俩种不同的拉伸区域的.9图片造成的不同效果:
图a和图b的不同点在于: 图a的左侧只在箭头的下面画了个黑点,而图b的左侧在箭头的上下面都各自画了个黑点。
从右手边的预览图,我们也可以看出图a在纵向拉伸时,只会拉伸箭头下方那个黑点所在的区域。而图b在纵向拉伸时,箭头上下方的区域都会进行拉伸。
为了更直观的看出效果,可在Draw 9-patch工具中,Patch scale是进行拉伸的倍数选择,可将它由最小值滑到最大值,以在预览图中观察效果。
同时,我们在真机中进行编译看效果:
三. .9图片的使用2 -- padding效果
1.下:黑色区域表示横向的内容显示区域
2.右:黑色区域表示纵向的内容显示区域
在Draw 9-patch工具中,勾选Show content,可以在右手边的预览区域看到紫色的区域就是内容显示的区域。
我们来看一个使用了下方和右方黑点的和没有使用的区别:
由图中,我们可以很直观的看出,使用了下方/右方黑点的可以适当调整文字内容在图片中的区域。其实就是实现android:padding的效果,即设置内边距。
下方黑点区域的左端实现&android:paddingLeft ,右端实现android:paddingRight
右方黑点区域的上端实现android:paddingTop,下端实现android:paddingBottom
同样,可在Draw 9-patch工具中,Patch scale是进行拉伸的倍数选择,可将它由最小值滑到最大值,以在预览图中观察效果。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:10439次
排名:千里之外
原创:41篇
(1)(1)(2)(11)(14)(1)(11)温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
“点九”是andriod平台的应用软件开发里的一种特殊的图片形式,文件扩展名为:.9.png&智能手机中有自动横屏的功能,同一幅界面会在随着手机(或平板电脑)中的方向传感器的参数不同而改变显示的方向,在界面改变方向后,界面上的图形会因为长宽的变化而产生拉伸,造成图形的失真变形。我们都知道android平台有多种不同的分辨率,很多控件的切图文件在被放大拉伸后,边角会模糊失真。OK,在android平台下使用点九PNG技术,可以将图片横向和纵向同时进行拉伸,以实现在多分辨率下的完美显示效果。【普通拉伸和点九拉伸效果对比】对比很明显,使用点九后,仍能保留图像的渐变质感,和圆角的精细度。从中我们也可以理解为什么叫“点九PNG”,其实相当于把一张png图分成了9个部分(九宫格),分别为4个角,4条边,以及一个中间区域,4个角是不做拉升的,所以还能一直保持圆角的清晰状态,而2条水 平边和垂直边分别只做水平和垂直拉伸,所以不会出现边会被拉粗的情况,只有中间用黑线指定的区域做拉伸。结果是图片不会走样二.“点九”的制作方法方法1:使用 “draw9patch”工具绘制,流程如下1.&&安装工具首先你需要给自己的电脑安装上java于系统的默认目录下。没有安装java的同学可以在百度搜索:jdk-6u20-windows-i586,安装包大小80M左右。然后使用andriod模拟器—android-sdk-windows,打开SDK/tools目录下的“draw9patch.bat”文件,出现载入窗口:2.导入并编辑将png图片拖拽到该窗口中如下图,自动进入编辑界面。图中介绍了每个区域的内容及功能注释。预览右侧的视图发现,图片的边缘处于普通拉伸状态。现在我们在图片边缘点击左键,绘制出黑线,即图片需要被拉伸的部分。如下图,对4条黑线做了注释。如果失误多绘的部分,可按住shift键的同时点击鼠标左键擦除)。如图所见,三种拉伸结果均已完美显示,已实现我们想要的拉伸效果,假设这是一个有显示文字的窗体,那么文字显示的区域,程序也会控制在黑线对应范围。以下这些图片,包括异性(非规则图形)图片,也可以通过点九PNG实现横纵向的自然拉伸。【draw9patch.bat其他功能说明】②&&&Show lock:显示不可绘区域② Show patches:预览这个绘图区中的可延伸宫格(粉红色代表一个可延伸区域)③ Show patches:预览视图中的高亮区域(紫色区域)④ Show bad patches:在宫格区域四周增加一个红色边界,这可能会在图像被延伸时产生人工痕迹。如果你消除所有的坏宫格,延伸视图的视觉一致性将得到维护。3.保存和输出点击左上file- save,保存文件,自动生成一张后缀名为“*.9.png”格式的图片,图片上下左右各增加了1px的黑线。方法2:直接使用 PS等平面工具绘制,流程图如下如流程图所示,相对与方法1,只需2个步骤就可得到.9.png图片,具体步骤为:1.&&确定切图后直接改变图片的画布大小,2.&&手动将上下左右各增加1px3.&&使用铅笔工具,手动绘制拉伸区域,色值必须为黑色(#000000)。4.&&存储为web所用格式,选择png-24,储存时手动将后缀名改为.9.png不过这种方法的缺点是不能实时预览,判断并测试拉伸区域的准确性。使用此方法需要注意以下2点:1.&手绘的黑线拉伸区必须是#000000,透明度100%,并且图像四边不能出现半透明像素;2.&你的.9.png必须绘有拉伸区域的黑线;否则,图片不会通过android系统编译,导致程序报错。还有,有同学疑惑解压缩apk文件后,.9.png图片里的黑线怎么没了?那是因为andriod程序在把文件打包成apk的时候,程序会自动把*.9.png图片边缘的黑线去掉,所以解压缩apk后看到的.9.png文件是没有黑线的。三.使用“点九”的意义关于下图,经过测试发现使用普通png的显示效果出现明显的变色横纹。而.9.png图片的显示效果明显优于普通png。使用.9.png格式后,横纹问题基本已解决。因为对于.9.png图片,android系统程序有对其优化的算法。由于android手机屏幕的材质质量差距大。很多屏幕不支持16位以上的颜色显示。所以渲染后结果出现丢失颜色,故造成横纹显示。经与多款android手机对比后发现,屏幕越次的手机横纹越明显。而使用了*.9.png图片技术后,只需要采用一套界面切图去适配不同的分辨率,而且大幅减少安装包的大小。而且这样程序不需要专门做处理的就可以实现其拉伸,也减少了代码量和开发工作量。相信每个人android平台的切图工作,会有不同的技巧和心得,非常欢迎大家能在评论中留下自己的个人经验及心得。相互交流会让我们的工作模式更灵活,更高效,同时带给大家更多优质的移动端应用)。转载自:个人觉得刚开始HUI的童鞋可以使用第一种方法,这样能够实时预览拉伸后的效果。
阅读(4406)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'点九(draw9patch)图片如何制作',
blogAbstract:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}

我要回帖

更多关于 draw9patch怎么打开 的文章

 

随机推荐