首页 > 代码库 > 深入理解Libgdx中的Skin类
深入理解Libgdx中的Skin类
本文不是直接翻译。。。本文在Libgdx的官方wiki的基础上,加上一些自己的理解。所以,难免会一些甚至是很多的理解很片面的东西。写的不好,还请见谅。。。。
其实
其实,在LibGDX的官方文档对Skin这个类的介绍中,其主要介绍了以下几个方面:
1、往Skin里面添加资源的两种方式。
2、从Skin中获取资源的方式。
第一种方式:以atlas为操作对象:
atlas = new TextureAtlas(Gdx.files.internal("meijia.atlas"), Gdx.files.internal("")); skin = new Skin();//Skin求是就是一个资源管理类... skin.addRegions(atlas); region = skin.get("BG1", TextureRegion.class);
解析:对于skin.get(name,type)中的name,它与atlas文件中的资源的名字是一致的。也就是说他与atlas.findRegion(name)中的name是一样的。
以下对skin的get(name,type)的源码进行以下分析:
public <T> T get (String name, Class<T> type) {//根据类型和名字返回相应的资源 //如果name(名字)或者是类型(type)为空,则抛出参数非法异常(IllegalArgumentException)和相应的提示信息 if (name == null) throw new IllegalArgumentException("name cannot be null."); if (type == null) throw new IllegalArgumentException("type cannot be null."); //判断想要获取的类型是否是TDNS(TextureRegion、Drawable、NinePatch、Sprite)中的一种,如果是调用相应的getXXX()方法 if (type == Drawable.class) return (T)getDrawable(name); if (type == TextureRegion.class) return (T)getRegion(name); if (type == NinePatch.class) return (T)getPatch(name); if (type == Sprite.class) return (T)getSprite(name); //如果不是上面的4种类型,则去资源中看一下是否有这种类型(type)及名字(name)的资源存在. ObjectMap<String, Object> typeResources = resources.get(type); if (typeResources == null) throw new GdxRuntimeException("No " + type.getName() + " registered with name: " + name); Object resource = typeResources.get(name); if (resource == null) throw new GdxRuntimeException("No " + type.getName() + " registered with name: " + name); return (T)resource;
小结:也就是说skin.get(name,type)这个函数主要干了这么一件事:
1)先看一下参数是否符合,如果不符合则抛出相应的异常及提示信息。
2)如果参数没有什么错误的话,就去找找type是否指TDNS(关于这个是什么意思请看上面的源码分析)类型,如果是,则直接返回。
3)否则再去resource中找是否有类型为type,名字为name的这么一种资源。如果没有则抛出相应的异常及提示信息
skin.add("color", Color.RED); Color color = skin.getColor("color");解释:
对于上面的“Color color = skin.getColor("color");”或许写成Color color1 = skin.get("green", Color.class);会比较符合初学者的心态。嗯嗯,其实getColor(name)函数实现的时候会去调get(name,Color.class)这个函数。也就是说
Libgdx官方wiki中所提到的“Convinience methods(便利方法)”getXXX(name)函数底层都是去调相应的get(name,XXX)函数。事实胜于雄辩,源码面前无秘密。
以下贴出libgdx中的Skin类中关于这几个函数的实现。
public Color getColor (String name) { return get(name, Color.class); }
public BitmapFont getFont (String name) { return get(name, BitmapFont.class); }
/** Returns a registered texture region. If no region is found but a texture exists with the name, a region is created from the * texture and stored in the skin. */ public TextureRegion getRegion (String name) { TextureRegion region = optional(name, TextureRegion.class); if (region != null) return region; Texture texture = optional(name, Texture.class); if (texture == null) throw new GdxRuntimeException("No TextureRegion or Texture registered with name: " + name); region = new TextureRegion(texture); add(name, region, Texture.class); return region; }
/** Returns a registered tiled drawable. If no tiled drawable is found but a region exists with the name, a tiled drawable is * created from the region and stored in the skin. */ public TiledDrawable getTiledDrawable (String name) { TiledDrawable tiled = optional(name, TiledDrawable.class); if (tiled != null) return tiled; Drawable drawable = optional(name, Drawable.class); if (tiled != null) { if (!(drawable instanceof TiledDrawable)) { throw new GdxRuntimeException("Drawable found but is not a TiledDrawable: " + name + ", " + drawable.getClass().getName()); } return tiled; } tiled = new TiledDrawable(getRegion(name)); add(name, tiled, TiledDrawable.class); return tiled; }
/** Returns a registered ninepatch. If no ninepatch is found but a region exists with the name, a ninepatch is created from the * region and stored in the skin. If the region is an {@link AtlasRegion} then the {@link AtlasRegion#splits} are used, * otherwise the ninepatch will have the region as the center patch. */ public NinePatch getPatch (String name) { NinePatch patch = optional(name, NinePatch.class); if (patch != null) return patch; try { TextureRegion region = getRegion(name); if (region instanceof AtlasRegion) { int[] splits = ((AtlasRegion)region).splits; if (splits != null) { patch = new NinePatch(region, splits[0], splits[1], splits[2], splits[3]); int[] pads = ((AtlasRegion)region).pads; if (pads != null) patch.setPadding(pads[0], pads[1], pads[2], pads[3]); } } if (patch == null) patch = new NinePatch(region); add(name, patch, NinePatch.class); return patch; } catch (GdxRuntimeException ex) { throw new GdxRuntimeException("No NinePatch, TextureRegion, or Texture registered with name: " + name); } }
/** Returns a registered sprite. If no sprite is found but a region exists with the name, a sprite is created from the region * and stored in the skin. If the region is an {@link AtlasRegion} then an {@link AtlasSprite} is used if the region has been * whitespace stripped or packed rotated 90 degrees. */ public Sprite getSprite (String name) { Sprite sprite = optional(name, Sprite.class); if (sprite != null) return sprite; try { TextureRegion textureRegion = getRegion(name); if (textureRegion instanceof AtlasRegion) { AtlasRegion region = (AtlasRegion)textureRegion; if (region.rotate || region.packedWidth != region.originalWidth || region.packedHeight != region.originalHeight) sprite = new AtlasSprite(region); } if (sprite == null) sprite = new Sprite(textureRegion); add(name, sprite, NinePatch.class); return sprite; } catch (GdxRuntimeException ex) { throw new GdxRuntimeException("No NinePatch, TextureRegion, or Texture registered with name: " + name); } }
/** Returns a registered drawable. If no drawable is found but a region, ninepatch, or sprite exists with the name, then the * appropriate drawable is created and stored in the skin. */ public Drawable getDrawable (String name) { Drawable drawable = optional(name, Drawable.class); if (drawable != null) return drawable; drawable = optional(name, TiledDrawable.class); if (drawable != null) return drawable; // Use texture or texture region. If it has splits, use ninepatch. If it has rotation or whitespace stripping, use sprite. try { TextureRegion textureRegion = getRegion(name); if (textureRegion instanceof AtlasRegion) { AtlasRegion region = (AtlasRegion)textureRegion; if (region.splits != null) drawable = new NinePatchDrawable(getPatch(name)); else if (region.rotate || region.packedWidth != region.originalWidth || region.packedHeight != region.originalHeight) drawable = new SpriteDrawable(getSprite(name)); } if (drawable == null) drawable = new TextureRegionDrawable(textureRegion); } catch (GdxRuntimeException ignored) { } // Check for explicit registration of ninepatch, sprite, or tiled drawable. if (drawable == null) { NinePatch patch = optional(name, NinePatch.class); if (patch != null) drawable = new NinePatchDrawable(patch); else { Sprite sprite = optional(name, Sprite.class); if (sprite != null) drawable = new SpriteDrawable(sprite); else throw new GdxRuntimeException("No Drawable, NinePatch, TextureRegion, Texture, or Sprite registered with name: " + name); } } add(name, drawable, Drawable.class); return drawable; }
3、Skin在创建UI控件中的使用。
第一种方式:
TextButtonStyle buttonStyle = skin.get("bigButton", TextButtonStyle.class); TextButton button = new TextButton("Click me!", buttonStyle);
第二种方式:
TextButton button = new TextButton("Click me!", skin, "bigButton");
当没有第三个参数的时候j将默认去skin中找名为default的资源
4、拷贝Skin里面的资源
官方原话:
Resources obtained from the skin are not new instances, the same object is returned each time. If the object is modified, the changes will be reflected throughout the application. If this is not desired, a copy of the object should be made.
The newDrawable
method copies a drawable. The new drawable‘s size information can be changed without affecting the original. The method can also tint a drawable.
用法:
//修改资源..拷贝(copy)skin里面的资源 Drawable pinkDrawable = skin.newDrawable("BG1",Color.PINK); image = new Image(pinkDrawable);
以下是官方wiki中的部分文字的部分翻译:其实看懂上面的东西就行了。因为官方wiki基本讲的就是这些东西。。
Overview 综述
The Skin class stores resources for UI widgets to use. It is a convenient container for texture regions, ninepatches, fonts, colors, etc. Skin also provides convenient conversions, such as retrieving a texture region as a ninepatch, sprite, or drawable.
Skin这个类主要是为UI 组件存储一些资源(Resource).它也提供了一些方便的转换。如存进去的时候是Texture类型,取出来的时候可以直接当成TextureRegion类型去出来(其实这里面是先取name为XXX的TextureRegion,假如取不到,就尝试去取name为XXX的Texture,如果能娶到,再通过取到的Texture生成TextureRegion,并存进Skin中)。
Skin files from the libgdx tests can be used as a starting point. You will need: uiskin.png, uiskin.atlas, uiskin.json, and default.fnt. This enables you to quickly get started using scene2d.ui and replace the skin assets later.
libgdx tests这个项目中(也就是官方提供的Gdx-tests的这个例子)的skin 的相关文件来作为学习Skin这个类的起点。你将需要 相应的.png
.fnt 、atlas、json文件来作为学习Skin这个类的起点。他们能帮助你很快的学习Skin。
Resources in a skin typically come from a texture atlas, widget styles and other objects defined using JSON, and objects added to the skin via code. Even when JSON is not used, it is still recommended to use Skin with a texture atlas and objects added via code. This is much more convenient to obtain instances of drawables and serves as a central place to obtain UI resources.