自定义控件,较常用View、ViewGroup、Scroller三个类,其继承关系如下:
本示例自定义控件,实现一个Gallery效果,并添加了一个显示View个数和位置的bar条,效果图:
自定义控件,包含通过继承实现的自定义控件和自定义控件属性两部分,即控件和属性
1、自定义属性
自定义属性,分为定义属性、解析属性、设置属性三部分,具体步骤:
首先,在res/valus/attrs.xml属性资源文件中,定义控件属性
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <declare-styleable name="com.myapps.widget.Pager">
- <attr name="pageWidth" format="dimension" />
- </declare-styleable>
- <declare-styleable name="com.myapps.widget.PagerBar">
- <attr name="barColor" format="color" />
- <attr name="highlightColor" format="color" />
- <attr name="fadeDelay" format="integer" />
- <attr name="fadeDuration" format="integer" />
- <attr name="roundRectRadius" format="dimension" />
- </declare-styleable>
- </resources>
然后,在自定义控件的代码中,解析自定义的属性,如在PagerBar.java:
- // 自定义属性
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.com_myapps_widget_PagerBar);
- int barBackColor = a.getColor(R.styleable.com_myapps_widget_PagerBar_barColor, DEFAULT_BAR_BACKCOLOR); // bar背景色
- int barForeColor = a.getColor(R.styleable.com_myapps_widget_PagerBar_highlightColor, DEFAULT_BAR_FORECOLOR); // bar前景色
- fadeDelay = a.getInteger(R.styleable.com_myapps_widget_PagerBar_fadeDelay, DEFAULT_FADE_DELAY); // bar消失延迟时间
- fadeDuration = a.getInteger(R.styleable.com_myapps_widget_PagerBar_fadeDuration, DEFAULT_FADE_DURATION); // bar消失动画时间
- ovalRadius = a.getDimension(R.styleable.com_myapps_widget_PagerBar_roundRectRadius, 2f);
- a.recycle();
最后,在布局文件中设置属性,如在main.xml
- <com.homer.mycontrol.PagerBar
- android:id="@+id/control"
- android:layout_width="fill_parent"
- android:layout_height="4dip"
- android:layout_margin="8dip"
- myapps:roundRectRadius="2dip" /> <!-- 自定义圆角 -->
其中,在布局中间main.xml中,需要注意:
xmlns:myapps="http://schemas.android.com/apk/res/com.homer.mycontrol"
定义属性时,在declare-styleable的name中,需要包含com.myapps.widget.PagerBar,表示自定义的控件PageBar是widget子类,myapps是xmlns解析标记
解析属性时,在TypedArray中,需要包含R.styleable.com_myapps_widget_PagerBar,横线替换了圆点.
定义属性时,在com.homer.mycontrol.PagerBar中,需要包含myapps:roundRectRadius="2dip",加上myapps解析标记
2、自定义控件PagerBar
自定义PagerBar,在图片下方用来显示图片滑到了第几页,即上面效果图(图2、图3)中的下部银白色细条,具体实现:
- public PagerBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- // 自定义属性
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.com_myapps_widget_PagerBar);
- int barBackColor = a.getColor(R.styleable.com_myapps_widget_PagerBar_barColor, DEFAULT_BAR_BACKCOLOR); // bar背景色
- int barForeColor = a.getColor(R.styleable.com_myapps_widget_PagerBar_highlightColor, DEFAULT_BAR_FORECOLOR); // bar前景色
- fadeDelay = a.getInteger(R.styleable.com_myapps_widget_PagerBar_fadeDelay, DEFAULT_FADE_DELAY); // bar消失延迟时间
- fadeDuration = a.getInteger(R.styleable.com_myapps_widget_PagerBar_fadeDuration, DEFAULT_FADE_DURATION); // bar消失动画时间
- ovalRadius = a.getDimension(R.styleable.com_myapps_widget_PagerBar_roundRectRadius, 2f);
- a.recycle();
- barBackPaint = new Paint();
- barBackPaint.setColor(barBackColor);
- barForePaint = new Paint();
- barForePaint.setColor(barForeColor);
- fadeOutAnimation = new AlphaAnimation(1f, 0f);
- fadeOutAnimation.setDuration(fadeDuration);
- fadeOutAnimation.setRepeatCount(0);
- fadeOutAnimation.setInterpolator(new LinearInterpolator());
- fadeOutAnimation.setFillEnabled(true);
- fadeOutAnimation.setFillAfter(true);
- }
- public int getNumPages() {
- return numPages;
- }
- public void setNumPages(int numPages) {
- if (numPages <= 0) {
- throw new IllegalArgumentException("numPages must be positive");
- }
- this.numPages = numPages;
- invalidate(); // 重绘View
- fadeOut(); // 设置bar消失效果
- }
- /** bar消失动画 */
- private void fadeOut() {
- if (fadeDuration > 0) {
- clearAnimation();
- fadeOutAnimation.setStartTime(AnimationUtils.currentAnimationTimeMillis() + fadeDelay); //延迟fadeDelay后动画开始
- setAnimation(fadeOutAnimation);
- }
- }
- /** @return 0 to numPages-1 */
- public int getCurrentPage() {
- return currentPage;
- }
- /** @param currentPage 0 to numPages-1 */
- public void setCurrentPage(int currentPage) {
- if (currentPage < 0 || currentPage >= numPages) {
- throw new IllegalArgumentException("currentPage parameter out of bounds");
- }
- if (this.currentPage != currentPage) {
- this.currentPage = currentPage;
- this.position = currentPage * getPageWidth(); // bar前景色滑动条的起始位置(像素值)
- invalidate();
- fadeOut();
- }
- }
- /** 获取View的宽度,即bar的宽度 */
- public int getPageWidth() {
- return getWidth() / numPages; // getWidth()是PagerBar的宽度(减去了margin左右距离后)
- }
- /** @param position can be -pageWidth to pageWidth*(numPages+1) */
- public void setPosition(int position) {
- if (this.position != position) {
- this.position = position;
- invalidate();
- fadeOut();
- }
- }
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), ovalRadius, ovalRadius, barBackPaint); // 绘制bar背景
- canvas.drawRoundRect(new RectF(position, 0, position + (getWidth() / numPages), getHeight()), ovalRadius, ovalRadius, barForePaint); // 绘制bar前景
- }