Android UI开发详解之模板控件的复用

简介: Android的UI设计一直是Android程序员比较苦恼的一件事,本文主要讲解如何将一些模板类控件进行复用,从而简化UI的开发。 如图: 我们很多程序的界面中,顶部的TopBar是不变的,所以,我们可以做一个公用的控件模板,每次使用时,只要设置相应的参数,就能生成这样一个TopBar。

Android的UI设计一直是Android程序员比较苦恼的一件事,本文主要讲解如何将一些模板类控件进行复用,从而简化UI的开发。

如图:

我们很多程序的界面中,顶部的TopBar是不变的,所以,我们可以做一个公用的控件模板,每次使用时,只要设置相应的参数,就能生成这样一个TopBar。

模板控件实现方法:

package com.xys.multiplexedmodule;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MultipleTopBar extends RelativeLayout{
	
	private Button btn_left;
	private Button btn_right;
	private TextView tv_title;
	
	private TopBarClickListener topBarClickListener;
	private String str_title;
	
	private RelativeLayout.LayoutParams leftButtonLayoutParams;
	private RelativeLayout.LayoutParams rightButtonLayoutParams;
	private RelativeLayout.LayoutParams tvTitleLayoutParams;
	
	private static int leftBtnId=1;
	private static int titleTvId=2;
	private static int rightBtnId=3;
	
	private Drawable leftBtnBackground;
	private Drawable rightBtnBackground;
	
	private String str_LeftBtn;
	private String str_RightBtn;
	private int leftBtnColor;
	private int rightBtnColor;
	private int titleTvColor;
	
	private float titleTextSize;
	
	public MultipleTopBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		//从参数列表中获取参数
		//TypedArray实例是个属性的容器,context.obtainStyledAttributes()方法返回得到。AttributeSet是节点的属性集合
		//第二个参数为 为获取到值时的默认值
		TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.TopBar);
		this.str_title=ta.getString(R.styleable.TopBar_title);
		this.leftBtnBackground=ta.getDrawable(R.styleable.TopBar_leftBackground);
		this.rightBtnBackground=ta.getDrawable(R.styleable.TopBar_rightBackground);
		this.str_LeftBtn=ta.getString(R.styleable.TopBar_leftText);
		this.str_RightBtn=ta.getString(R.styleable.TopBar_rightText);
		this.leftBtnColor=ta.getColor(R.styleable.TopBar_leftTextColor, 0);
		this.rightBtnColor=ta.getColor(R.styleable.TopBar_rightTextColor, 0);
		this.titleTextSize=ta.getDimension(R.styleable.TopBar_titleTextSize, 14);
		this.titleTvColor=ta.getColor(R.styleable.TopBar_titleTextColor, 0);
		
		ta.recycle();
		
		btn_left=new Button(context);
		btn_right=new Button(context);
		tv_title=new TextView(context);
		
		btn_left.setId(leftBtnId);
		btn_right.setId(rightBtnId);
		tv_title.setId(titleTvId);
		
		//为组件配置布局参数
		leftButtonLayoutParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
		rightButtonLayoutParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
		tvTitleLayoutParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
		
		leftButtonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,RelativeLayout.TRUE);
		leftButtonLayoutParams.setMargins(12, 0, 0, 0);//左上右下
		leftButtonLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
        
		rightButtonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,RelativeLayout.TRUE);
		rightButtonLayoutParams.setMargins(0, 0, 12, 0);//左上右下
		rightButtonLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
        
		tvTitleLayoutParams.setMargins(12, 0, 12, 0);//左上右下
		tvTitleLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
		tvTitleLayoutParams.addRule(RelativeLayout.LEFT_OF, rightBtnId);
		tvTitleLayoutParams.addRule(RelativeLayout.RIGHT_OF, leftBtnId);
		//tvTitleLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
		tv_title.setGravity(Gravity.CENTER);
		tv_title.setBackgroundColor(leftBtnColor);
        
        addView(btn_left, leftButtonLayoutParams);
        addView(btn_right,rightButtonLayoutParams);
        addView(tv_title,tvTitleLayoutParams);
        
        //btn_left.setBackgroundDrawable(leftBtnBackground);
        btn_left.setText(str_LeftBtn);
        btn_left.setTextColor(leftBtnColor);
        //btn_right.setBackgroundDrawable(rightBtnBackground);
        btn_right.setText(str_RightBtn);
        btn_right.setTextColor(rightBtnColor);
        
        tv_title.setTextSize(22.0f);
        tv_title.setTextColor(Color.BLUE);
        tv_title.setEllipsize(TruncateAt.MIDDLE);
        tv_title.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);
        tv_title.setSingleLine(true);
        tv_title.setText(str_title);
        tv_title.setTextSize(titleTextSize);
        tv_title.setTextColor(titleTvColor);
        
        btn_left.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					if(topBarClickListener!=null){
                        topBarClickListener.leftBtnClick();
                }
				}
        });
        
        btn_right.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                        if(topBarClickListener!=null){
                                topBarClickListener.rightBtnClick();
                        }
                }
        });
		
	}
	
	/*
	 * 单击监听事件
	 */
	public void setTopBarClickListener(TopBarClickListener topBarClickListener){
		this.topBarClickListener=topBarClickListener;
	}
}


监听接口:

package com.xys.multiplexedmodule;

public interface TopBarClickListener {

	void leftBtnClick();
	void rightBtnClick();
}

对我们自定义的模板控件,我们需要设定他的一些参数,在Values下新建attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--declare-styleable:自定义属性的值  -->
    <declare-styleable name="TopBar">
        <attr name="title" format="string" />
        <attr name="titleTextSize" format="dimension" />
        <attr name="titleTextColor" format="color" />
        <attr name="leftTextColor" format="color" />
        <attr name="leftBackground" format="string" />
        <attr name="leftText" format="string" />
        <attr name="rightTextColor" format="color" />
        <attr name="rightBackground" format="string" />
        <attr name="rightText" format="string" />
    </declare-styleable>

</resources>

现在我们就已经做好了一个模板,我们要如何使用他呢,很简单:

测试类:

package com.xys.multiplexedmodule;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.Toast;

public class TestActivity extends Activity {

	private MultipleTopBar topBar;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        topBar=(MultipleTopBar)findViewById(R.id.topBar);
        topBar.setTopBarClickListener(new TopBarClickListener() {
			
			@Override
			public void rightBtnClick() {
				// TODO Auto-generated method stub
				Toast.makeText(TestActivity.this, "你点击的是右边的按钮", Toast.LENGTH_LONG).show();
			}
			
			@Override
			public void leftBtnClick() {
				// TODO Auto-generated method stub
				Toast.makeText(TestActivity.this, "你点击的是左边的按钮", Toast.LENGTH_LONG).show();
			}
		});
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
}

引用模板的布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res/com.xys.multiplexedmodule"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".TestActivity" >
	<!--一定要加入引用 xmlns:custom="http://schemas.android.com/apk/res/com.xys.multiplexedmodule"  -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:orientation="vertical" >

        <com.xys.multiplexedmodule.MultipleTopBar
            android:id="@+id/topBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            custom:leftBackground="@drawable/ic_launcher"
            custom:leftText="左侧"
            custom:leftTextColor="#ff0000"
            custom:rightBackground="@drawable/ic_launcher"
            custom:rightText="右侧"
            custom:rightTextColor="#ff0000"
            custom:title="自定义标题"
            custom:titleTextColor="#123412"
            custom:titleTextSize="14.0sp" >
        </com.xys.multiplexedmodule.MultipleTopBar>
    </LinearLayout>

</RelativeLayout>

这样我们就可以使用我们新建的模板控件了,效果如下:


目录
相关文章
|
开发框架 前端开发 JavaScript
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发一
本文介绍了方舟开发框架(ArkUI)及其两种开发范式:基于ArkTS的声明式开发范式和类Web开发范式。ArkUI是用于构建HarmonyOS应用界面的UI框架,提供极简UI语法和基础设施。声明式开发范式使用ArkTS语言,以组件、动画和状态管理为核心,适合复杂团队协作;类Web开发范式采用HML、CSS、JavaScript三段式开发,适用于简单界面应用,贴近Web开发者习惯。文中还概述了两者的架构和基础能力,帮助开发者选择合适的范式进行高效开发。
447 15
|
编解码 前端开发 Java
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发三
本文介绍了基于声明式UI范式的图形绘制与动画效果实现方法,涵盖绘制图形、添加动画效果及常见组件说明三部分内容。在绘制图形部分,详细讲解了如何通过Circle组件为食物成分表添加圆形标签,以及使用Path组件结合SVG命令绘制自定义图形(如应用Logo)。动画效果部分则展示了如何利用animateTo实现闪屏动画,包括渐出、放大效果,并设置页面跳转;同时介绍了页面间共享元素转场动画的实现方式。最后,文章列举了声明式开发范式中的各类组件及其功能,帮助开发者快速上手构建复杂交互页面。
462 11
|
9月前
|
存储 消息中间件 人工智能
【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡
【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡
566 4
|
9月前
|
存储 开发者 容器
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
本文介绍了ArkTS语言中的Class类、泛型、接口、模块化、自定义组件及状态管理等核心概念,并结合代码示例讲解了对象属性、构造方法、继承、静态成员、访问修饰符等内容,同时涵盖了路由管理、生命周期和Stage模型等应用开发关键知识点。
628 1
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
|
JavaScript 前端开发 UED
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发四
本文介绍了Web组件开发与性能优化的相关内容。在Web组件开发部分,涵盖创建组件、设置样式与属性、添加事件和方法以及场景示例,如动态播放视频。性能提升方面,推荐使用数据懒加载、条件渲染替代显隐控制、Column/Row替代Flex、设置List组件宽高及调整cachedCount减少滑动白块等方法,以优化应用性能与用户体验。
381 56
|
编解码 UED 开发者
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发之常见布局
本文主要介绍了自适应布局与响应式布局的相关内容。自适应布局部分涵盖线性布局、层叠布局、弹性布局和网格布局,详细说明了各布局的特性及使用方法,例如线性布局中的排列、拉伸与缩放,弹性布局的方向、换行与对齐方式等。响应式布局则重点讲解了栅格系统和媒体查询,阐述如何通过栅格组件和媒体查询条件实现不同设备上的适配效果。这些技术帮助开发者灵活应对多尺寸屏幕的设计需求,提升用户体验。
590 55
|
存储 开发框架 API
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发二
本文详细介绍了基于声明式UI开发的健康饮食应用的设计与实现过程。内容涵盖从基础环境搭建到复杂功能实现的全流程,包括创建简单视图、构建布局(如Stack、Flex)、数据模型设计、列表与网格布局构建,以及页面跳转和数据传递等核心功能。 本文通过实际案例深入浅出地解析了声明式UI开发的关键技术和最佳实践,为开发者提供了宝贵的参考。
489 14
|
人工智能 物联网 编译器
【01】优雅草星云物联网AI智控系统从0开发鸿蒙端适配完成流程-初始化鸿蒙编译器deveco studio项目结构-UI设计图切片下载-优雅草卓伊凡
【01】优雅草星云物联网AI智控系统从0开发鸿蒙端适配完成流程-初始化鸿蒙编译器deveco studio项目结构-UI设计图切片下载-优雅草卓伊凡
392 11
【01】优雅草星云物联网AI智控系统从0开发鸿蒙端适配完成流程-初始化鸿蒙编译器deveco studio项目结构-UI设计图切片下载-优雅草卓伊凡
|
JavaScript 前端开发 开发者
09.HarmonyOS Next数据驱动UI开发:ForEach与动态渲染完全指南(上)
在现代前端开发中,数据驱动UI已成为主流开发范式。HarmonyOS Next的ArkTS语言和声明式UI框架完美支持这一理念,使开发者能够以更高效、更直观的方式构建复杂应用。
328 1
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
702 2

热门文章

最新文章