Hello everyone, I am Lu Yao, every Friday I will recommend you a high-quality Github project of pan-mobile terminal.

Today’s hero is BackgroundLibrary, which generates shapes directly from tags without having to write shape.xml.

Author github.com/JavaNoober
Url Github.com/JavaNoober/…
Language Java
Star 3.2 k.
Fork 420
Issue 5 Open/128 Closed
Commits 186
Last Update 18 Dec 2021
License Apache-2.0

The above data is as of Feb. 12, 2022.

use

The painful experience of hand-writing shaper. XML and selector. XML, I believe that every Android programmer has a deep experience. BackgroundLibiary provides a less invasive solution.

First, introduce dependencies.

allprojects { repositories { ... maven { url 'https://jitpack.io' } } } implementation "androidx.appcompat:appcompat:$supportVersion" implementation 'com. Making. JavaNoober. BackgroundLibrary: library: 1.6.9'Copy the code

Just use the app:bl_xxx attribute in the XML. Here is a simple example.

<TextView
    android:layout_width="130dp"
    android:layout_width="130dp"
    android:layout_height="36dp"
    android:gravity="center"
    android:text="TextView"
    android:textColor="#8c6822"
    android:textSize="20sp"
    app:bl_corners_radius="4dp"
    app:bl_solid_color="#E3B666"
    app:bl_stroke_color="#8c6822"
    app:bl_stroke_width="2dp" />
Copy the code

This is the same thing as

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="2dp"/>
    <solid android:color="#E3B666"/>
    <stroke android:color="#E3B666" android:width="2dp"/>
</shape>
Copy the code

BackgroundLibrary supports a large number of properties, a list of which can be found on the wiki: github.com/JavaNoober/… .

In addition to the basic use in XML, BackgroundLibrary provides complete support.

Drawable can be generated directly in code.

Drawable Drawable = new drawablecreator.builder ().setcornersRadius (dip2px(20)) .setGradientAngle(0).setGradientColor(Color.parseColor("#63B8FF"), Color.parseColor("#4F94CD")).build(); btn.setBackground(drawable); Tvtest1. setClickable(true); // For Android source code reasons, you must call, Otherwise, ColorStateList colors = new DrawableCreator.Builder().setPressedTextColor(Color.RED).setUnPressedTextColor(Color.BLUE).buildTextColor(); tvTest1.setTextColor(colors);Copy the code

Live Templates can be configured for code prompting to reduce usage costs. See wiki: github.com/JavaNoober/… .

The preview function is provided, but the original View needs to be replaced by the corresponding BLView in the frame, which has a certain cost.

Overall, it’s a pretty good library for getting rid of shape.xml, but it’s not a complete replacement. Since using BackgroundLibrary means giving up reuse, shape.xml is more often used together.

The principle of

The principle of BackgroundLibrary is very clever. Two key words: automatic initialization, automatic attribute resolution. You can stop looking back and think about how to do it.

The automatic initialization, of course, takes advantage of the ContentProvider.

public class BackgroundContentProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        if(getContext() != null && getContext() instanceof Application && BLAutoInjectController.isEnableAutoInject()){
            BackgroundLibrary.inject(getContext());
            ((Application) getContext()).registerActivityLifecycleCallbacks(new BLActivityLifecycleRegister());
        }
        return true;
    }
  ...
}
Copy the code

RegisterActivityLifecycleCallbacks (new BLActivityLifecycleRegister ()) to monitor all the life cycle of the Activity.

public class BLActivityLifecycleRegister implements Application.ActivityLifecycleCallbacks { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { BackgroundLibrary.inject(activity); }... }Copy the code

The key is backgroundLibrary.inject (activity).

public class BackgroundLibrary {
​
    public static LayoutInflater inject(Context context) {
        LayoutInflater inflater;
        if (context instanceof Activity) {
            inflater = ((Activity) context).getLayoutInflater();
        } else {
            inflater = LayoutInflater.from(context);
        }
        if (inflater == null) {
            return null;
        }
        if (inflater.getFactory2() == null) {
            BackgroundFactory factory = setDelegateFactory(context);
            inflater.setFactory2(factory);
        } else if (!(inflater.getFactory2() instanceof BackgroundFactory)) {
            forceSetFactory2(inflater);
        }
        return inflater;
    }
  ...
}
Copy the code

If you know how AppcompatActivity can automatically convert a TextView in an XML file to AppcompatTextView at runtime, you should understand how BackgroundLibrary works as well. This is all because of LayoutInflater setFactory. If you don’t understand LayoutInflater setFactory, you can read this article.

The last

That’s all for this introduction, and I’ll see you next Friday.

If you have a good project recommendation, feel free to leave a message to me.