美文网首页 Android知识进阶(遥远的重头开始)
Android-自定义View-自定义属性之第三方Banner看

Android-自定义View-自定义属性之第三方Banner看

作者: MonkeyLei | 来源:发表于2019-07-12 09:47 被阅读2次

上一篇我们简单实践了下自定义属性部分Android-自定义View-自定义属性,现在我们看看第三方的自定义控件源码,混个眼熟先。

Like,youth5201314/banner,下载一下zip包,然后解压,AS导入module即可:

image

1. 从我们经常使用的类(Banner)+配置入手(app:)

     <com.youth.banner.Banner
        android:id="@+id/finba_banner"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        app:banner_default_image="@drawable/home_list_img_default"
        app:banner_layout="@layout/banner_me"
        app:image_scale_type="center_crop"
        app:indicator_drawable_selected="@drawable/banner_rectangle_white_radius"
        app:indicator_drawable_unselected="@drawable/banner_rectangle_gray_radius"
        app:indicator_height="4dp"
        app:indicator_margin="3dp"
        app:indicator_width="10dp"
        app:title_textsize="16sp" />
image

2. 看构造函数 - 是不是会有之前相识的感觉妮?

 public Banner(Context context) {
        this(context, null);
    }

    public Banner(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public Banner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        titles = new ArrayList<>();
        imageUrls = new ArrayList<>();
        imageViews = new ArrayList<>();
        indicatorImages = new ArrayList<>();
        dm = context.getResources().getDisplayMetrics();
        indicatorSize = dm.widthPixels / 80;
        initView(context, attrs);
    }

这个地方没有第四个构造函数,因为第四个是5.0以后新增的,所以这个暂时不需要也没关系。你看上面的写法,是不是和之前我们了解的一样。或许我们今后开始自定义做自己的自定义控件就是这样的方式吧!

3. 重点看下自定义View的部分的具体操作 - handleTypedArray(...)

image

Banner.java

    private void handleTypedArray(Context context, AttributeSet attrs) {
        if (attrs == null) {
            return;
        }
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Banner);
        mIndicatorWidth = typedArray.getDimensionPixelSize(R.styleable.Banner_indicator_width, indicatorSize);
        mIndicatorHeight = typedArray.getDimensionPixelSize(R.styleable.Banner_indicator_height, indicatorSize);
        mIndicatorMargin = typedArray.getDimensionPixelSize(R.styleable.Banner_indicator_margin, BannerConfig.PADDING_SIZE);
        mIndicatorSelectedResId = typedArray.getResourceId(R.styleable.Banner_indicator_drawable_selected, R.drawable.gray_radius);
        mIndicatorUnselectedResId = typedArray.getResourceId(R.styleable.Banner_indicator_drawable_unselected, R.drawable.white_radius);
        scaleType = typedArray.getInt(R.styleable.Banner_image_scale_type, scaleType);
        delayTime = typedArray.getInt(R.styleable.Banner_delay_time, BannerConfig.TIME);
        scrollTime = typedArray.getInt(R.styleable.Banner_scroll_time, BannerConfig.DURATION);
        isAutoPlay = typedArray.getBoolean(R.styleable.Banner_is_auto_play, BannerConfig.IS_AUTO_PLAY);
        titleBackground = typedArray.getColor(R.styleable.Banner_title_background, BannerConfig.TITLE_BACKGROUND);
        titleHeight = typedArray.getDimensionPixelSize(R.styleable.Banner_title_height, BannerConfig.TITLE_HEIGHT);
        titleTextColor = typedArray.getColor(R.styleable.Banner_title_textcolor, BannerConfig.TITLE_TEXT_COLOR);
        titleTextSize = typedArray.getDimensionPixelSize(R.styleable.Banner_title_textsize, BannerConfig.TITLE_TEXT_SIZE);
        mLayoutResId = typedArray.getResourceId(R.styleable.Banner_banner_layout, mLayoutResId);
        bannerBackgroundImage = typedArray.getResourceId(R.styleable.Banner_banner_default_image, R.drawable.no_banner);
        typedArray.recycle();
    }

其实就是获取我们使用banner进行配置时的一些个属性。同时如果你不设置也是有默认值的。获取如下配置哟....TypedArray,不就是我们之前了解过的获取方式么。

image

其中有一个属性app:banner_layout我特别提一下(因为很多时候可以自定义banner的样式满足产品需求,所以我们有必要关注;同时banner的一些个源码我也自定义过一些实现,所以我觉得加深对框架的理解还是蛮重要的)

image

3.1 然后你可以看看它如下的布局呀,属性配置文件呀,基本也就熟套了...

image

**3.2 **其他的文件也可以过过眼,有时间一定要研究一下,因为文件和代码不多,所以相对来讲还好。而且你如果利用Viewpaper实现过banner无限轮播控件的话,看起这个应该不会那么的难了。

image

主要是几个部分:Banner(具体的控件实现,对外提供) + 滑动动画(transformer) + 图片加载器....其中BannerScroller部分用到了ViewPaper的一个方法mScroller,这个方法是通过反射获取 - 所以关于反射的知识有必要学习,我前面有文章了解过Android-自定义注解-反射基础

     private void initViewPagerScroll() {
        try {
            Field mField = ViewPager.class.getDeclaredField("mScroller");
            mField.setAccessible(true);
            mScroller = new BannerScroller(viewPager.getContext());
            mScroller.setDuration(scrollTime);
            mField.set(viewPager, mScroller);
        } catch (Exception e) {
            Log.e(tag, e.getMessage());
        }
    }

4. 最后关于我改动的地方,提一下,就是一个文本显示关键字高亮背景的效果

image

主要就是利用SpannableString进行背景颜色文本显示。

先看高亮工具类 HighLightKeyWordUtil.java

package com.youth.banner;

import android.content.Context;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HighLightKeyWordUtil {
    /**
     * @param color 关键字颜色
     * @param text 文本
     * @param keyword 关键字
     * @return
     */
    public static SpannableString getHighLightKeyWord(int color, String text, String keyword) {
        SpannableString s = new SpannableString(text);
        Pattern p = Pattern.compile(keyword);
        Matcher m = p.matcher(s);
        while (m.find()) {
            int start = m.start();
            int end = m.end();
            s.setSpan(new ForegroundColorSpan(color), start, end,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return s;
    }

    /**
     * @param color 关键字颜色
     * @param text 文本
     * @param keyword 多个关键字
     * @return
     */
    public static SpannableString getHighLightKeyWord(int color, String text,String[] keyword) {
        SpannableString s = new SpannableString(text);
        for (int i = 0; i < keyword.length; i++) {
            Pattern p = Pattern.compile(keyword[i]);
            Matcher m = p.matcher(s);
            while (m.find()) {
                int start = m.start();
                int end = m.end();
                s.setSpan(new ForegroundColorSpan(color), start, end,
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        return s;
    }

    /**
     * @param color 关键字背景颜色
     * @param text 文本
     * @param keyword 关键字
     * @return
     */
    public static SpannableString getBackgroudKeyWord(int tvcolor, int color, String text, String keyword) {
        SpannableString s = new SpannableString(text);
        Pattern p = Pattern.compile(keyword);
        Matcher m = p.matcher(s);
        //while (m.find()) {
        if (m.find()) {
            int start = m.start();
            int end = m.end();
            s.setSpan(new RoundBackgroundColorSpan(color, tvcolor, 10), start, end,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return s;
    }

    /**
     * @param color 关键字背景颜色
     * @param text 文本
     * @param keywords 多个关键字
     * @return
     */
    public static SpannableString getBackgroudKeyWord(int[] tvcolor, int[] color, String text, String[] keywords) {
        SpannableString s = new SpannableString(text);
        int strLength = 0;
        for (int i = 0; i < keywords.length; i++) {
            ///< 必须是开头的才标记背景,所以索引必须小于开头内容长度
            strLength += keywords[i].length();

            Pattern p = Pattern.compile(keywords[i]);
            Matcher m = p.matcher(s);
            ///< 只找开头的,标题中的不找
            //while (m.find()) {
            //if (m.find()) {
            if (m.find() && m.start() < strLength) {
                int start = m.start();
                int end = m.end();
                s.setSpan(new RoundBackgroundColorSpan(color[i], tvcolor[i], 10), start, end,
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        return s;
    }
}

**然后使用的地方Banner.java --- **//bannerTitle.setText(titles.get(position - 1));是之前的写法

   @Override
    public void onPageSelected(int position) {
        ......
         case BannerConfig.CIRCLE_INDICATOR_TITLE:
                bannerTitle.setText(HighLightKeyWordUtil.getBackgroudKeyWord(
                        new int[]{Color.parseColor("#ffffff"), Color.parseColor("#ffffff")},
                        new int[]{Color.parseColor("#febc48"), Color.parseColor("#f13b2f")},
                        titles.get(position - 1), new String[]{"独家", "首发"}));
                //bannerTitle.setText(titles.get(position - 1));
                break;
        ......
    }

Last,基本的自定义属性和获取我们大概来讲下。这个框架相对还好,不是特别复杂。有些框架就复杂了,不仅仅是这点代码了。而且可能还融合了其他的优秀的第三方,所以看起来相对更难一些。 不过我们慢慢来嘛。顺便也已多看看别人做框架是怎么做的,怎么别人如此优秀,而自己菜的像渣渣妮...

不是心灵鸡汤 -- 轻轻的我将离开你,请将眼角的泪拭去.....嘿嘿!

相关文章

  • Android-自定义View-自定义属性之第三方Banner看

    上一篇我们简单实践了下自定义属性部分Android-自定义View-自定义属性,现在我们看看第三方的自定义控件源码...

  • Android-自定义View-onMeasure方法

    上一篇的自定义属性中Android-自定义View-自定义属性,我们进行了属性的xml设置以及构造方法里面获取对应...

  • Android-自定义View-自定义属性

    上一篇Android-自定义View-onDraw方法起步我们已经基本了解了绘制。不过有点不太灵活,大部分小白作者...

  • A008-drawable资源

    关于drawable资源笔者之前有写过两篇文章:Android-自定义图像资源的使用(1)Android-自定义图...

  • angular自定义指令相关知识及代码

    大纲 1、自定义指令之——属性指令2、自定义属性指令的运行原理3、自定义属性指令代码实践4、自定义结构指令5、自定...

  • 2019-12-23

    自定义view画渐变图形,inflate 自定义view:画渐变图形 参考:自定义View-第十六步:Linear...

  • 自定义banner

    启动springboot应用的时候,会打印出默认的banner, 如何关闭自定义的banner? 如何自定义ban...

  • 如何使用自定义属性

    1.预习: Android自定义控件之自定义属性 format详解 2.在attrs.xml中创建自定义属性 其中...

  • Android-自定义ViewGroup(二) 侧滑菜单

    为加深自定义ViewGroup实现思想,所以自己写了一个SlidingMenu,实现方式类似Android-自定义...

  • Android-自定义banner实现

    惯例先上图: 可以看到这是一个轮播图,只不过我们以前在用的时候一般都是用ViewPager,用正常的ViewPag...

网友评论

    本文标题:Android-自定义View-自定义属性之第三方Banner看

    本文链接:https://www.haomeiwen.com/subject/gxgskctx.html