上一篇我们通过在布局文件中include的方法,引用标题栏进行复用。下面我们将标题栏封装为View,并可以实现在布局中设置属性,和在Java代码中通过各种方法设置。
首先还是上一篇中的标题栏布局 titlebar.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="@color/bg_white">
<TextView
android:id="@+id/titlebar_tv"
android:layout_centerInParent="true"
android:gravity="center"
android:maxWidth="224dp"
style="@style/TextViewTitle"
/>
<TextView
android:id="@+id/titlebar_tv_left"
style="@style/TextViewTitleSide"
/>
<TextView android:id="@+id/titlebar_tv_right"
style="@style/TextViewTitleSide"
android:layout_alignParentRight="true"/>
<ImageView android:id="@+id/titlebar_iv_left"
style="@style/ImageViewTitleSide"/>
<ImageView android:id="@+id/titlebar_iv_right"
style="@style/ImageViewTitleSide"
android:layout_alignParentRight="true"/>
</RelativeLayout>
其中的自定义style:
<style name="TextViewTitle">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:singleLine">true</item>
<item name="android:textSize">@dimen/txt_title</item>
<item name="android:textColor">@color/txt_black</item>
</style>
<style name="TextViewTitleSide">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
<item name="android:gravity">center</item>
<item name="android:visibility">gone</item>
<item name="android:paddingLeft">16dp</item>
<item name="android:paddingRight">16dp</item>
<item name="android:textSize">@dimen/txt_subhead</item>
<item name="android:textColor">@color/txt_black</item>
</style>
<style name="ImageViewTitleSide">
<item name="android:layout_width">48dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:visibility">gone</item>
<item name="android:padding">12dp</item>
</style>
新建TitleBar.java,它就是我们今天的主角了,我们的自定义控件。继承自RelativeLayout,在构造方法中inflate布局,而且还要暴露一些方法,titlebar.xml:
public class TitleBar extends RelativeLayout{
TextView tv;
TextView tv_left;
TextView tv_right;
ImageView iv_left;
ImageView iv_right;
public TitleBar(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout. titlebar, this);
tv = (TextView) findViewById(R.id.titlebar_tv);
tv_left = (TextView) findViewById(R.id.titlebar_tv_left);
tv_right = (TextView) findViewById(R.id.titlebar_tv_right);
iv_left = (ImageView) findViewById(R.id.titlebar_iv_left);
iv_right = (ImageView) findViewById(R.id.titlebar_iv_right);
}
public TitleBar setTitle(String str) {
tv.setText(str);
return this;
}
public TitleBar setTextLeft(String str) {
tv_left.setVisibility(View.VISIBLE);
tv_left.setText(str);
return this;
}
public TitleBar setTextRight(String str) {
tv_right.setVisibility(View.VISIBLE);
tv_right.setText(str);
return this;
}
public TitleBar setTextLeftGONE() {
tv_right.setVisibility(View.GONE);
return this;
}
public TitleBar setImageLeftRes(int Res) {
setTextLeftGONE();
iv_left.setVisibility(View.VISIBLE);
iv_left.setImageResource(Res);
return this;
}
public TitleBar setImageRightRes(int Res) {
iv_right.setVisibility(View.VISIBLE);
iv_right.setImageResource(Res);
return this;
}
public void setListener(final TitleListenr listenr){
if(tv_left.getVisibility() == View.VISIBLE) {
tv_left.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listenr.onLeftClickListener();
}
});
}
if(iv_left.getVisibility() == View.VISIBLE) {
iv_left.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listenr.onLeftClickListener();
}
});
}
if(tv_right.getVisibility() == View.VISIBLE) {
iv_left.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listenr.onRightClickListener();
}
});
}
if(iv_right.getVisibility() == View.VISIBLE) {
iv_left.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listenr.onRightClickListener();
}
});
}
}
public interface TitleListenr{
void onLeftClickListener();
void onRightClickListener();
}
}
我们自定义了TitleListenr接口,这样在一个方法中同时可以设置两个监听事件。 在布局文件中添加控件。这样我们完成了一期工程。 现在我们想在布局文件中也可以设置控件的属性。
新建attrs.xml,利用declare-styleable实现自定义控件属性。
<resources>
<declare-styleable name="TitleBar">
<attr name="titleText" format="string"/>
<attr name="tv_left" format="string"/>
<attr name="tv_right" format="string"/>
<attr name="iv_left" format="reference"/>
<attr name="iv_right" format="reference"/>
<attr name="tv_left_visibility">
<enum name="visible" value="0"/>
<enum name="invisible" value="4"/>
<enum name="gone" value="8"/>
</attr>
<attr name="tv_right_visibility">
<enum name="visible" value="0"/>
<enum name="invisible" value="4"/>
<enum name="gone" value="8"/>
</attr>
<attr name="iv_left_visibility">
<enum name="visible" value="0"/>
<enum name="invisible" value="4"/>
<enum name="gone" value="8"/>
</attr>
<attr name="iv_right_visibility">
<enum name="visible" value="0"/>
<enum name="invisible" value="4"/>
<enum name="gone" value="8"/>
</attr>
</declare-styleable>
</resources>
完善TitleBar.java中的代码,使属性的设置能有些卵用:
...
public TitleBar(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout. titlebar, this);
tv = (TextView) findViewById(R.id.titlebar_tv);
tv_left = (TextView) findViewById(R.id.titlebar_tv_left);
tv_right = (TextView) findViewById(R.id.titlebar_tv_right);
iv_left = (ImageView) findViewById(R.id.titlebar_iv_left);
iv_right = (ImageView) findViewById(R.id.titlebar_iv_right);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitleBar);
String title = a.getString(R.styleable.TitleBar_titleText);
String tv_leftText = a.getString(R.styleable.TitleBar_tv_left);
String tv_rightText = a.getString(R.styleable.TitleBar_tv_right);
Drawable iv_leftDraw = a.getDrawable(R.styleable.TitleBar_iv_left);
Drawable iv_rightDraw = a.getDrawable(R.styleable.TitleBar_iv_right);
int tv_left_visible = a.getInt(R.styleable.TitleBar_tv_left_visibility, 8);
int tv_right_visible = a.getInt(R.styleable.TitleBar_tv_right_visibility, 8);
int iv_left_visible = a.getInt(R.styleable.TitleBar_iv_left_visibility, 8);
int iv_right_visible = a.getInt(R.styleable.TitleBar_iv_right_visibility, 8);
tv.setText(title);
tv_left.setText(tv_leftText);
tv_right.setText(tv_rightText);
iv_left.setImageDrawable(iv_leftDraw);
iv_right.setImageDrawable(iv_rightDraw);
tv_left.setVisibility(tv_left_visible);
tv_right.setVisibility(tv_right_visible);
iv_left.setVisibility(iv_left_visible);
iv_right.setVisibility(iv_right_visible);
a.recycle();
}
...
接着在activtiy_second.xml布局文件中进行一些设置
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:my="http://schemas.android.com/apk/res/wang.titledemo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<view.TitleBar
android:id="@+id/titleBarId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
my:titleText = "haha"
my:tv_right = "右"
my:tv_right_visibility = "visible"
/>
</LinearLayout>
这里注意要在开头进行引用,类似Java中的import。
在SecondActivity.class中进行设置,当然首先要findView:
public class SecondActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_second);
TitleBar titleBar = (TitleBar) findViewById(R.id.titleBarId);
titleBar.setTextLeft("后退").setListener(new TitleListenr() {
@Override
public void onRightClickListener() {
}
@Override
public void onLeftClickListener() {
finish();
}
});
}
}
在代码中的设置会覆盖掉xml文件中的配置,和所有其他的View一样。当然在代码中,也可以用上一篇替代的Builder设计模式,方法完全一样。
end.