Android代码获取资源文件和系统属性

目录

 

一 获取资源文件

1.通过资源文件名称获取资源Id

2.简化代码

3.总结

二 获取系统属性

 三 总结


一 获取资源文件

1.通过资源文件名称获取资源Id

前几天在自定义Toast的时候,为了能够使用系统原生Toast的UI,所以就想着怎么引用Toast的布局文件。通过查Toast的源码发现,其实Toast的布局文件为transient_notification。

  public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
            @NonNull CharSequence text, @Duration int duration) {
        Toast result = new Toast(context, looper);

        LayoutInflater inflate = (LayoutInflater)
                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
        TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
        tv.setText(text);

        result.mNextView = v;
        result.mDuration = duration;

        return result;
    }

那么如果能直接引用这个布局文件给到自定义Toast的UI,那么就可以与系统Toast保持一致。然后就发现了Resources中有一个非常好用的方法:

  public int getIdentifier(String name, String defType, String defPackage) 

其中

扫描二维码关注公众号,回复: 12776010 查看本文章

name:资源文件的名字,不需要添加后缀名;

defType:资源文件所在的目录,例如values、drawable、layout、anim、string等;

defPackgage:就是该资源文件所在的包名。

有了这个神奇的方法,我们就可以轻松的下面的资源文件。

所以在自定义Toast中,就将该transient_notification布局文件应用到代码中,实现了和系统的Toast保持一致的风格。

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        @LayoutRes int layout = mContext.getResources().getIdentifier("transient_notification", "layout", "android");
        View v = inflater.inflate(layout, null);
        mMessageView = v.findViewById(android.R.id.message);

2.简化代码

 其实getResources().getIdentifier()这个方法还可以去简化代码,例如我们在使用帧动画AnimationDrawable(虽然帧动画在使用的过程中存在OOM的问题,现在只是来说明下getResources().getIdentifier()的另外一个用法)的时候,通常的做法有两种:

  • 方法1

(1)在drawable下定义frame.xml文件,然后直接将该drawable文件赋值给ImageView,然后通过 AnimationDrawable anim = (AnimationDrawable) ivFrame.getDrawable();获取到该帧动画,进行播放。由于不是本文介绍的内容,所以不做详细展开说明。

  • 方法2:

(1)在布局文件中还是定义ImageView控件

    <ImageView
        android:id="@+id/iv_frame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/frame" />

(2)在java代码中使用代码播放动画

    public void animationDrawable(View view) {
        AnimationDrawable drawable = new AnimationDrawable();
        drawable.addFrame(getDrawable(R.drawable.frame00), 200);
        drawable.addFrame(getDrawable(R.drawable.frame01), 200);
        drawable.addFrame(getDrawable(R.drawable.frame02), 200);
        drawable.addFrame(getDrawable(R.drawable.frame03), 200);
        drawable.addFrame(getDrawable(R.drawable.frame04), 200);
        drawable.addFrame(getDrawable(R.drawable.frame05), 200);
        drawable.addFrame(getDrawable(R.drawable.frame06), 200);
        drawable.addFrame(getDrawable(R.drawable.frame07), 200);
        drawable.addFrame(getDrawable(R.drawable.frame08), 200);
        drawable.addFrame(getDrawable(R.drawable.frame09), 200);
        drawable.addFrame(getDrawable(R.drawable.frame10), 200);
        drawable.addFrame(getDrawable(R.drawable.frame11), 200);
        drawable.start();
    }

对于这种方法的代码,其实有一些冗余代码来添加一些有规律的资源文件frame00~frame11 ,其实我们可以用这个getResources().getIdentifier()来简化代码,使得代码更加简洁,改造之后代码如下:

    public void animationDrawable(View view) {
        AnimationDrawable drawable = new AnimationDrawable();
        for (int i = 0; i < 12; i++) {
            String index = i < 10 ? ("0" + i) : String.valueOf(i);
            int drawableId = getResources().getIdentifier(String.format("frame%s", index), "drawable", getPackageName());
            Drawable db = getDrawable(drawableId);
            drawable.addFrame(db, 200);
        }
        drawable.start();
    }

瞬间10几行的代码就简化到5行的代码,使得代码简洁很多。 

3.总结

getResources().getIdentifier()这个方法可以在知道资源名称的情况下,就可以获取到对应的资源Id,有了资源Id,那么就可以根据对应的get方法,得到对应的内容。另外我们可以用来加载一些有规律的资源文件来简化代码,保持代码简洁。

二 获取系统属性

Android View属性设置优先级的一点总结中也提到了可以使用obtainStyledAttributes来获取到自定义的属性。那如果我们要获取到布局文件中的一些系统属性值,该怎么处理呢?当然提供了一些系统方法供我们去调用,譬如在一个自定义View中我们需要获取到layout_width的值,我们可以用getMeasuredWidth()来获取到对应的值,但是如果我们在构造函数中就需要获取到该值呢?因为自定义View在构造函数调用的时候,还没有走到onMeasure()方法,getMeasuredWidth()值是为0的,那么就可以使用obtainStyledAttributes来获取layout_width值。

 public final TypedArray obtainStyledAttributes(
            @Nullable AttributeSet set, @NonNull @StyleableRes int[] attrs)

在这个方法中,第一个参数set就是我们在布局文件中定义该View的时候设置的布局参数,d第二个参数attrs就是我们要获取哪些属性值的数组,如果要获取 layout_width的值,那么只需要,将layout_width放到一个数组中,传入到第二个参数即可:

    private void initAttribute(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        if (attrs == null) {
            return;
        }
        int[] attrsArray = new int[]{android.R.attr.layout_width, android.R.attr.background};
        TypedArray array = getContext().obtainStyledAttributes(attrs, attrsArray);
        if (array == null) {
            return;
        }
//第一个参数与传入的attrsArray的索引值对应
        int layout_width = array.getLayoutDimension(0, -1);
        Drawable background = array.getDrawable(1);
    }

 三 总结

现在越来越发现Android的有些内容真的是很好玩的,对于源码也需要继续研究。加油吧

猜你喜欢

转载自blog.csdn.net/nihaomabmt/article/details/110484139
今日推荐