【问题标题】:Draw complex drawable in api lower than 23在低于23的api中绘制复杂的drawable
【发布时间】:2015-09-24 15:37:04
【问题描述】:

我正在尝试绘制由圆形和矩形组成的可绘制对象。它在 api 设置为 23 时工作正常。我注意到在最新的 api 中添加了以下“item”属性:高度、重力、重量。是否有可能在旧的sdk中获得效果?

可绘制:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:height="5dp"
        android:gravity="center_vertical"
        android:left="5dp">
        <shape android:shape="rectangle">
            <size
                android:width="50dp"
                android:height="5dp" />
            <solid android:color="#125572" />
        </shape>
    </item>
    <item
        android:width="20dp"
        android:height="20dp"
        android:gravity="center_vertical">
        <shape android:shape="oval">
            <solid android:color="#125572" />
            <size
                android:width="20dp"
                android:height="20dp" />
        </shape>
    </item>
</layer-list>

使用 api 23 的图像:

使用 api 22 的图像:

【问题讨论】:

  • 为什么不使用 ShapeDrawable 和传递给自定义的 Shape 对象?

标签: java android drawable android-drawable xml-drawable


【解决方案1】:

我知道这个问题已经很老了,但我解决了这个问题,也许它现在对某人有用。

对于解决方案,我创建了两个类。

一个名为 MyLayerDrawable 的类扩展了 LayerDrawable。关于这个类要记住的重要一点是,您可以获得每一层的顶部和左侧插图。

public class MyLayerDrawable extends LayerDrawable{


private List<Layer> layers;

//some code here

public static class Layer{
    private Drawable drawable;
    private int topInset;
    private int leftInset;
    public Layer(Drawable drawable,int topInset,int leftInset){
        this.leftInset=leftInset;
        this.drawable=drawable;
        this.topInset=topInset;
    }
    public Drawable getDrawable(){
        return drawable;
    }
    public int getTopInset(){
        return topInset;
    }
    public int getLeftInset(){return leftInset;}
}

我创建的第二个类叫做 MyImageViewPatch,它拥有一个 ImageView。 该类的唯一公共方法是 setImageMyLayerDrawable(MyLayerDrawable layerDrawable)。此方法将设置图像可绘制对象委托给它拥有的 ImageView:

public void setImageMyLayerDrawable(MyLayerDrawable layerDrawable){
    imageView.setImageDrawable(layerDrawable);

}

但在调用 setImageDrawable 方法之前,已在 MyImageViewPatch 构造函数中将观察者对象添加到 ImageView。在 ImageView 中绘制 Drawable 之前调用此观察者:

        imageView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            MyLayerDrawable layerDrawable=(MyLayerDrawable)imageView.getDrawable();
            int numberOfLayers=layerDrawable.getNumberOfLayers();
            Drawable drawable;
            Rect bounds;


            for(int i=0;i<numberOfLayers;i++){//for each layer
                drawable=layerDrawable.getDrawable(i);
                bounds=drawable.getBounds();
                bounds.top=layerDrawable.getLayer(i).getTopInset();
                bounds.left=layerDrawable.getLayer(i).getLeftInset();
                if(drawable.getIntrinsicHeight()<bounds.height()){
                    bounds.bottom=drawable.getIntrinsicHeight()+layerDrawable.getLayer(i).getTopInset();

                }
                if(drawable.getIntrinsicWidth()<bounds.width()){
                    bounds.right=drawable.getIntrinsicWidth()+layerDrawable.getLayer(i).getLeftInset();
                }
            }
            return true;
        }
    });

正如您在绘制 MyLayerDrawable 之前所见,每个图层的边界都根据左侧和顶部插图进行调整;这是以正确大小而不是拉伸的方式绘制可绘制对象的关键部分。

这是形状 xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:height="5dp"
    android:gravity="center_vertical"
    android:left="5dp"
    android:top="8dp">
    <shape android:shape="rectangle">
        <size
            android:width="50dp"
            android:height="5dp" />
        <solid android:color="#125572" />
    </shape>
</item>

<item
android:width="20dp"
android:height="20dp">
<shape android:shape="oval">
    <solid android:color="#125572" />
    <size
        android:width="20dp"
        android:height="20dp" />
</shape>
</item>


</layer-list>

为了使矩形垂直居中,我使用了 android:top="8dp" 而不是 android:gravity="center_vertical"。

这是主要活动的代码:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ImageView iv=(ImageView)findViewById(R.id.imageView);
    MyLayerDrawable myLayerDrawable=MyLayerDrawable.Builder.build(getApplicationContext(),R.drawable.layer_d_example);
    MyImageViewPatch myImageViewPatch=new MyImageViewPatch(iv);
    myImageViewPatch.setImageMyLayerDrawable(myLayerDrawable);

}

}

我在 github 上有完整的代码。你可以去看看:https://github.com/marcosbses/my_layout_drawable.git

【讨论】:

    猜你喜欢
    • 2017-01-17
    • 1970-01-01
    • 2018-01-22
    • 2020-07-01
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多