我想编写类似的代码:
Context c = getContext();
Button b = new Button( c );
b.setBackground( new SvgDrawable( c.getAssets(), "iconImage.svg" ));
int pxWidth = Math.round( 48/*sp*/ // scaling to user preference
* c.getResources().getDisplayMetrics().scaledDensity/*px per sp*/ );
addView( b, new ViewGroup.LayoutParams( pxWidth, WRAP_CONTENT ));
// determines unspecified height from pxWidth and aspect ratio
但是没有SvgDrawable
。有什么可以替代我的SVG到按钮上?
请给出适用于任何IDE的答案。我不使用Studio或Eclipse。
答案 0 :(得分:1)
如果您的minSdkVersion为21或更高,正如您所说,那么您可以选择仅使用VectorDrawable
。只需使用其中一个在线转换器将SVG转换为VectorDrawable。
否则,您可以使用Button
并根据Surabhi的建议设置背景。
或者您可以使用ImageButton
并执行
// AndroidSVG
try {
SVG svg = SVG.getSVGFromAsset(getAssets(), "iconImage.svg");
yourButton.setImageDrawable(new PictureDrawable(svg.renderToPicture()));
}
catch (IOException e) {
e.printStackTrace();
}
或者如果你使用的是svg-android,那就是:
// svg-android
try {
SVG svg = SVGParser.getSVGFromAsset(getAssets(), "iconImage.svg");
yourButton.setImageDrawable(svg.createPictureDrawable());
}
catch (IOException e) {
e.printStackTrace();
}
答案 1 :(得分:0)
这样做:
try {
SVG svg = SVGParser.getSVGFromAsset(getAssets(), "iconImage.svg");
yourButton.setBackground(svg.createPictureDrawable());
} catch (IOException e) {
e.printStackTrace();
}
答案 2 :(得分:0)
这是我最终确定的解决方案。
矢量图像的首选形式通常是SVG,但Android上的本地首选项是VectorDrawable
。这引发了形式问题,我选择的解决方案是变换。
以下示例源是从使用Nashorn JavaScript编写的构建脚本中提取的。
var bufferFile = tmpDir.resolve( 'vectorDrawableBuffer.xml' ); // VD out
var inX = Build.xmlInputFactory().createXMLEventReader(
new (Java.type('java.io.BufferedInputStream'))(
new (Java.type('java.io.FileInputStream'))( sourceFile ))); // SVG in
var out = Files.newBufferedWriter( bufferFile );
try
{
var factory = Build.xmlEventFactory();
while( inX.hasNext() )
{
var xml = inX.next();
if( !xml.isStartElement()
|| xml.getName().getLocalPart() != 'svg' ) continue;
var parent;
var parents = []; // SVG
var _parents = []; // VectorDrawable
function indentLine()
{
out.newLine();
for( var p = parents.length; p > 0; --p ) out.append( '\t' );
}
// svg → vector
// - - - - - - -
out.append(
'<vector xmlns:a="http://schemas.android.com/apk/res/android"' );
parents.push( parent = 'svg' );
_parents.push( 'vector' );
var atts;
var att;
var name;
atts = xml.getAttributes();
while( atts.hasNext() )
{
att = atts.next();
name = att.getName().getLocalPart();
if( name == 'height' )
{
out.append( ' a:height="' )
.append( att.getValue() ).append( '"' );
}
else if( name == 'width' )
{
out.append( ' a:width="' )
.append( att.getValue() ).append( '"' );
}
else if( name == 'viewBox' )
{
// svg[viewBox] → vector[viewportWidth, viewportHeight]
// - - - - - - - - - - - - - - - - - - - - - - - - - - -
var b = att.getValue().split( ' ' );
if( /*min-x*/b[0] != '0' || /*min-y*/b[1] != '0' )
{
throw "Cannot transform, viewBox displaced from origin: "
+ sourceFile;
}
out.append( ' a:viewportWidth="' )
.append( b[2] ).append( '"' )
.append( ' a:viewportHeight="' )
.append( b[3] ).append( '"' );
}
}
out.append( '>' );
while( inX.hasNext() )
{
xml = inX.next();
if( xml.isStartElement() )
{
if( xml.getName().getLocalPart() != 'path' ) continue;
// path
// - - -
indentLine();
out.append( '<path' );
atts = xml.getAttributes();
while( atts.hasNext() )
{
att = atts.next();
name = att.getName().getLocalPart();
if( name == 'd' )
{
// path[d → pathData]
// - - - - - - - - - -
out.append( ' a:pathData="' )
.append( att.getValue() ).append( '"' );
}
else if( name == 'fill' )
{
// path[fill → fillColor]
// - - - - - - - - - - - -
out.append( ' a:fillColor="' )
.append( att.getValue() ).append( '"' );
}
}
out.append( '/>' );
}
else if( xml.isEndElement() )
{
name = xml.getName().getLocalPart();
if( name == parent )
{
indentLine();
out.append( '</' )
.append( _parents.pop() ).append( '>' );
}
}
}
}
}
finally
{
out.close();
inX.close();
}
请参阅original script file了解缺失的背景信息。
final Resources res = context.getResources();
final VectorDrawable icon;
// try
// {
// final Class<?> c =
// Class.forName( "android.graphics.drawable.VectorDrawable" );
// final Method m = c.getMethod( "create", Resources.class, int.class );
// icon = (VectorDrawable)m.invoke( null, res,
// R.drawable.vector_drawable_res_id );
// }
// catch( final Exception ex ) { throw new RuntimeException( ex ); }
//// call to API-hidden method, but better inline it for production code:
final XmlResourceParser p = res.getXml( R.drawable.vector_drawable_res_id );
try
{
// Go to first element, else VectorDrawable throws XmlPullParserException
// "Binary XML file line #-1<vector> tag requires viewportWidth > 0".
for( int t = p.getEventType(); t != START_TAG; t = p.next() )
{
if( t == END_DOCUMENT )
{
throw new XmlPullParserException( "Missing start tag" );
}
}
icon = new VectorDrawable();
icon.inflate( res, p, Xml.asAttributeSet(p) );
}
catch( final IOException|XmlPullParserException ex )
{
throw new RuntimeException( ex );
}
button.setBackground( icon );
最后,正如所承诺的那样:
final float aspectRatio =
(float)icon.getIntrinsicWidth() / icon.getIntrinsicHeight();
final int pxWidth = Math.round( 48/*sp*/ // scaling to user preference
* context.getResources().getDisplayMetrics().scaledDensity/*px per sp*/ );
final int pxHeight = Math.round( pxWidth / aspectRatio );
// icon.setBounds( /*left*/0, /*top*/0, pxWidth, pxHeight );
/// needn't scale icon itself, just the button:
addView( button, new ViewGroup.LayoutParams( pxWidth, pxHeight ));
这不是一个查看代码的简单解决方案。但我认为它将证明前进的可靠性(更少的意外陷阱和其他隐藏的复杂性)因为它使用了双方的首选形式:源端的SVG和可执行端的VectorDrawable
。