How to combine two dynamic speakers in Android?

so I have two different Drawables that I need to combine and get one Drawable at runtime. I want the first Drawable be above and the other below. I stumbled upon LayerDrawable , and it seems to me that this is exactly what I need, but I'm having problems setting up Drawables .

So, I have an ImageButton that is 48x48 dp , and here the final Drawable ends. The first Drawable is the plus button (20x20 dp ), and the second is a small dot (4x4 dp ) below the plus button.

The plus button Drawable loaded using font characters. I create a Drawable point button using this xml fragment:

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@color/white_40"/> <size android:width="4dp" android:height="4dp"/> </shape> 

My first approach was to simply add Drawables to the LayerDrawable , but when I do this, the width / height attributes of the point specified in the xml are ignored and stretched to cover the plus sign.

 LayerDrawable finalDrawable = new LayerDrawable(new Drawable[] {plusIcon, dotIcon}); 

The above results:



The second approach I tried was to use setLayerInset to try to position two Drawables .

  LayerDrawable finalDrawable = new LayerDrawable(new Drawable[] {plusIcon, dotIcon}); finalDrawable.setLayerInset(0, 0, 0, 0, 0); finalDrawable.setLayerInset(1, dp(22), dp(44), dp(22), 0); 

The above code fragment finished placing the point in the correct position, but also began to affect the position and size of the plus button, and it looked like this:
enter image description here

But I really want the plus button to be in the center of the ImageButton icon and the plus below it. Does anyone have an idea where I am wrong, and how can I correctly position two drawings?

PS: My application supports API 15+, so I can’t use a bunch of methods from the LayerDrawable API like setLayerGravity , `setPaddingMode, etc.

+5
source share
2 answers

Edit

This code will work at API levels below 23:

 ImageButton button = (ImageButton) findViewById(R.id.button); Drawable plusIcon = ContextCompat.getDrawable(this, R.drawable.plus); Drawable dotIcon = ContextCompat.getDrawable(this, R.drawable.oval); int horizontalInset = (plusIcon.getIntrinsicWidth() - dotIcon.getIntrinsicWidth()) / 2; LayerDrawable finalDrawable = new LayerDrawable(new Drawable[] {plusIcon, dotIcon}); finalDrawable.setLayerInset(0, 0, 0, 0, dotIcon.getIntrinsicHeight()); finalDrawable.setLayerInset(1, horizontalInset, plusIcon.getIntrinsicHeight(), horizontalInset, 0); button.setImageDrawable(finalDrawable); 

Original

The following code works for me:

 ImageButton button = (ImageButton) findViewById(R.id.button); Drawable plusIcon = ContextCompat.getDrawable(this, R.drawable.plus); Drawable dotIcon = ContextCompat.getDrawable(this, R.drawable.oval); LayerDrawable finalDrawable = new LayerDrawable(new Drawable[] {plusIcon, dotIcon}); finalDrawable.setLayerInsetBottom(0, dotIcon.getIntrinsicHeight()); finalDrawable.setLayerGravity(1, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL); button.setImageDrawable(finalDrawable); 

This leads to the following ui:

enter image description here

+2
source

Here is how I solved it:

 final View view = findViewById(R.id.view_in_layout); Drawable bottom = ContextCompat.getDrawable(context, R.drawable.ic_bottom); Drawable top = ContextCompat.getDrawable(context, R.drawable.ic_top); //bottom = index 0, top = index 1 final LayerDrawable layer = new LayerDrawable(new Drawable[]{bottom, top}); view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { //get the real height after it is calculated int height = view.getHeight(); //set the height half of the available space for example purposes, //the drawables will have half of the available height int halfHeight = height / 2; //the bottom drawable need to start when the top drawable ends layer.setLayerInset(0, 0, halfHeight, 0, 0); //the top drawable need to end before the bottom drawable starts layer.setLayerInset(1, 0, 0, 0, halfHeight); view.setBackground(layer); view.removeOnLayoutChangeListener(this); } }); 

You can choose different sizes for your drawings or move them using indexes. I used View.OnLayoutChangeListener(...) , for example, to wait for the current available view height

0
source

Source: https://habr.com/ru/post/1269910/


All Articles