很多时候我们所需要的控件不是简单的TextView、EditText、Button能够做到的,比如这个 。
其实上面这个控件很简单对吧,我们可以用shape来完成:
1.新建一个drawble文件
在res-drawable下新建一个circle.xml,root-element为shape:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/colorAccent" ></solid>
<!--<size android:height="10dp " android:width="10dp"></size>-->
</shape>
布局文件activity_second.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textName1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textViewOne"
android:textColor="@color/colorAccent"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/radio1"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_marginLeft="15dp"
android:background="@drawable/circle" />
<TextView
android:id="@+id/line1"
android:layout_width="50dp"
android:layout_height="1dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:background="@color/colorAccent"/>
</LinearLayout>
</LinearLayout>
这样子我们就得到了图片上那样的控件,然后我们需要做的是将这个控件组合起来以便于我们对其进行复用。
2.自定义组合控件
创建一个java类MyCustomerOrder,继承LinearLayout,实现三个构造函数,并创建一个initView方法,在Oncreate()中调用,在initView方法中添加布局文件
MyCustomerOrder.java:
public class CustomerOrder extends LinearLayout{
private TextView topText,circle,line;
public CustomerOrder(Context context) {
super(context);
}
public CustomerOrder(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomerOrder(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void initView() {
View view = View.inflate(getContext(),R.layout.activity_view,this);
topText = (TextView) view.findViewById(R.id.topText);
circle = (TextView) view.findViewById(R.id.circle);
line = (TextView) view.findViewById(R.id.line);
}
}
3.添加自定义控件
最后我们只需要在main.xml文件中添加我们的自定义控件即可:
<com.example.iworker.myview.MyCustomerOrder
android:id="@+id/order1"
android:layout_width="match_parent"
android:layout_height="50dp">
</com.example.iworker.myview.MyCustomerOrder>
4.装载自定义控件
最后在main文件中获得自定义控件并调用initView()方法载入布局即可:
MainActivity.java:
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customerOrder = (CustomerOrder) findViewById(R.id.custom);
customerOrder.initView();
}
这样我们就完成了我们自定义的一个控件。
4.动态添加UI
那么怎么动态添加UI呢,我们的目标是完成这个图片:
复制三个这样的控件,水平排列;
那么我们需要添加一个数组来存储三个控件,并用一个for循环来添加所需要的其他控件:
CustomerOrder.java:
public class CustomerOrder extends LinearLayout{
private TextView topText,circle,line;
private String[] titles;
public CustomerOrder(Context context) {
super(context);
//水平排列方法
setOrientation(HORIZONTAL);
}
public CustomerOrder(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(HORIZONTAL);
}
public CustomerOrder(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOrientation(HORIZONTAL);
}
public void init(String[] titles){
this.titles = titles;
initView();
}
public void initView() {
if(titles.length>0&&titles!=null){
for(int i = 0;i<titles.length;i++){
View view = View.inflate(getContext(),R.layout.activity_view,null);
topText = (TextView) view.findViewById(R.id.topText);
circle = (TextView) view.findViewById(R.id.circle);
line = (TextView) view.findViewById(R.id.line);
//添加控件方法
addView(view,LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
}
}
}
}
然后我们只需要在MainActivity中定义含有若干个对象的String数组,这里我只定义三个:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private String[] mTitles = new String[]{"hehe","haha","xixi"};
...
protected void onCreate(Bundle savedInstanceState) {
...
//调用init()
customerOrder.init(mTitles);
}
}
这样我们就可以灵活的添加控件啦,数量由我们自己决定。
再复杂一点
如果我们需要其中的一个控件的属性改变,比如颜色,我们该怎么做?我们先将文字改变一下:
在MainActivity.java中定义String数组
private String[] mTitles = new String[]{"已发送","配送中","配送完毕"};
在CustomerOrder.java中,将数组传入initView()中
public void init(String[] titles){
this.titles = titles;
initView(titles);
}
修改initView()方法
... topText.setText(mTitles[i]);
因为我们需要修改的是圆点的颜色、文字颜色和线条颜色,还有一个是第几个控件;因此我们先将它们定义一下,在设置对应方法:
CustomerOrder.java:
public class CustomerOrder extends LinearLayout{
...
private int currentView;//当前位置
private int circleColor;//圆点颜色
private int text;//文字
private int myTextColor;//文字颜色
private int lineColor;//线条颜色
...
//设置对应方法
/**
* 设置当前布局位置
* @param currentProcess
*/
public void setCurrentProcess(int currentProcess) {
this.currentView = currentProcess;
//获得当前布局的子View
View view = getChildAt(currentProcess);
TextView titleTextView = (TextView) view.findViewById(R.id.topText);
titleTextView.setTextColor(getResources().getColor(myTextColor));
TextView circleTextView = (TextView) view.findViewById(R.id.circle);
circleTextView.setBackground(getResources().getDrawable(circleColor));
TextView lineTextView = (TextView) view.findViewById(R.id.line);
lineTextView.setTextColor(getResources().getColor(lineColor));
//lineTextView.setVisibility(lineVisible);
// textView.setVisibility(GONE);
}
/**
* 设置圆点颜色
* @param circleColor
* @return
*/
public CustomerOrder setCircleColor(int circleColor){
this.circleColor = circleColor;
return this;
}
/**
* 设置文字颜色
* @param textColor
* @return
*/
public CustomerOrder setTextColor(int textColor){
this.myTextColor = textColor;
return this;
}
/**
* 设置文字
* @param text
* @return
*/
public CustomerOrder setText(int text){
this.text = text;
return this;
}
/**
* 设置线条颜色
* @param lineColor
* @return
*/
public CustomerOrder setLineColor(int lineColor){
this.lineColor = lineColor;
return this;
}
然后我们只需要在MainActivity.java文件中调用上面的方法即可随意更改颜色:
customerOrder.setTextColor(R.color.green);
customerOrder.setCircleColor(R.drawable.circle3);
customerOrder.setLineColor(R.color.green);
customerOrder.setCurrentProcess(2);
如果我们要隐藏掉最后一个控件的线条则可在Customer.java的initView(String[])方法中修改:
public void initView(String[] mTitles) {
...
if(i==mTitles.length-1){ line.setVisibility(GONE);
}
...
}
贴近现实
更现实的情况确实这样,在第二个圆点变化的时候,第一个圆点就已经变化了,在第三个圆点变化时,前两个也已经变了颜色,因此我们这样补充:
在 设置当前布局位置方法setCurrentProcess()中加入一个循环:
CustomerOrder.java
public void setCurrentProcess(int currentProcess) {
for(int i = 0;i<=currentProcess;i++){
//获得当前布局的子View
View view = getChildAt(i);
TextView titleTextView = (TextView) view.findViewById(R.id.topText);
titleTextView.setTextColor(getResources().getColor(myTextColor));
// titleTextView.setText(getResources().getText(text));
TextView circleTextView = (TextView) view.findViewById(R.id.circle);
circleTextView.setBackground(getResources().getDrawable(circleColor));
TextView lineTextView = (TextView) view.findViewById(R.id.line);
lineTextView.setBackgroundColor(getResources().getColor(lineColor));
}
优化代码
你以为这就完了吗?并没有。对于数组而言,事实上List会更好。