第一次发表博客,难免寒暄几句。见谅
学android大半年,学习途径嘛,无非视屏,百度,博客等等。更重要的多写,多思考。看各种大神都愿意把自己的理解,见解,想法跟大家分享,也许这不但是一种学习方式,也是一种学习态度。那么,从今天开始,自己也尝试去做这件事,当作自己学习的笔记,进步的历程,也当作给大家的分享。希望大家多多指教,互相学习。
先看看效果
大概就是这样子。之所以首发这篇文章,那是因为这是我们这次的任务,也是我对View有更深理解的一次任务,对Adapter中的getView方法的初步理解感悟。为什么提到Adapter呢,待会说。其中考试内容及扣分标准条数是不定的,也即需要主项、子项去适应
那么是如何实现的呢,其实原理也不难,我的方法是,使用shape,设置边框属性,然后在布局中background引用
新建text_stroke_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke
android:width="0.5dp"
android:color="#505050" />
<solid android:color="#ffffff"/>
</shape>
设置每个控件的android:background="@drawable/text_stroke_shape"很容易得到这样的布局,其宽度按比例设置为2:2:7:3:3:3:3
然后用ScrollView包裹剩下的布局,让View具有"扩展性",在竖直方向可以无限放大。
好,接下来说说主要部分思想及实现
用三个类去表示主项(Subject)、子项(Subhead)、及剩下的5个条目(Item),分别Subject类中有一个装载Subhead类的List,在Subhead中有装载Item类的List,这样就实现主项包含子项,子项包含条目的关系,便可用循环遍历一个Subject的集合方式,实例化布局,依次往父布局中装载子布局,从而实现布局可扩展性(有点类似ListVew加载View的方式吧,其实之前是用ListView做的,弄完之后发现有弊端,才改成这样)
类属性很简单,对应数量的String,装载下一级别的List
Subject.java
public class Subject {
private String subTitle;
private List<Subhead> subheadList = new ArrayList<Subhead>();
public Subject(String subTitle) {
super();
this.subTitle = subTitle;
}
public Subject() {
super();
}
public String getSubTitle() {
return subTitle;
}
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public List<Subhead> getSubheadList() {
return subheadList;
}
public void setSubheadList(List<Subhead> subheadList) {
this.subheadList = subheadList;
}
}
Subhead.java
public class Subhead {
private String subText;
private List<Item> itemList = new ArrayList<Item>();
public Subhead(String subText) {
this.subText = subText;
}
public Subhead() {
}
public String getSubTitle() {
return subText;
}
public void setSubTitle(String subText) {
this.subText = subText;
}
public List<Item> getItemList() {
return itemList;
}
public void setItemList(List<Item> itemList) {
this.itemList = itemList;
}
}
Item.java
public class Item {
private String content;
private String testType;
private String organization;
private String instruction;
private float deduct_points;
private float minPoint;
private float maxPoint;
public Item(String content, String testType, String organization,
float maxPoint) {
this.content = content;
this.testType = testType;
this.organization = organization;
this.maxPoint = maxPoint;
}
public Item(String content, String testType, String organization,
float minPoint, float maxPoint) {
this.content = content;
this.testType = testType;
this.organization = organization;
this.minPoint = minPoint;
this.maxPoint = maxPoint;
}
public Item(String content, String testType, String organization) {
this.content = content;
this.testType = testType;
this.organization = organization;
}
public Item() {
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTestType() {
return testType;
}
public void setTestType(String testType) {
this.testType = testType;
}
public String getOrganization() {
return organization;
}
public void setOrganization(String organization) {
this.organization = organization;
}
public String getInstruction() {
return instruction;
}
public void setInstruction(String instruction) {
this.instruction = instruction;
}
public float getDeduct_points() {
return deduct_points;
}
public void setDeduct_points(float deduct_points) {
this.deduct_points = deduct_points;
}
public float getMinPoint() {
return minPoint;
}
public void setMinPoint(float minPoint) {
this.minPoint = minPoint;
}
public float getMaxPoint() {
return maxPoint;
}
public void setMaxPoint(float maxPoint) {
this.maxPoint = maxPoint;
}
}
当然相应的,也需要3个布局去装载Subject,Subhead,Item3个类 看布局文件
subject_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/ll_second"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/text_stroke_shape"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_second"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="评分栏" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@drawable/text_stroke_shape"
android:gravity="center"
android:text="一、三项计划管控(10分)" />
<LinearLayout
android:id="@+id/ll_subhead"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="21"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_grade"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/text_stroke_shape"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_show_grade"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="评分栏" />
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_subtext"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@drawable/text_stroke_shape"
android:gravity="center"
android:text="(四)现场管理"
android:textSize="12sp" />
<LinearLayout
android:id="@+id/ll_item"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="19"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="7"
android:background="@drawable/text_stroke_shape"
android:gravity="center_vertical"
android:text="1.每发现1处煤矿未编制采掘作业计划的,扣3分;"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_testtype"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:background="@drawable/text_stroke_shape"
android:gravity="center"
android:text="查资料"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_organization"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:background="@drawable/text_stroke_shape"
android:gravity="center"
android:text="煤炭局"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_instruction"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:background="@drawable/text_stroke_shape"
android:ellipsize="end"
android:gravity="center"
android:text="暂无(点击添加)"
android:textColor="#0000ff"
android:singleLine="true"
android:textSize="12sp" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:orientation="horizontal" >
<EditText
android:id="@+id/et_deduct_points"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/text_stroke_shape"
android:focusable="false"
android:gravity="center"
android:inputType="numberDecimal"
android:padding="4dp"
android:singleLine="true"
android:text="3"
android:textColor="#ff0000"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
接下来就是创建View的时候了
InitView.java
public class InitView implements OnClickListener {
private Context mContext;
private List<Subject> subjectList;
private ViewGroup ll_main_content;
private TextView tv_over;
public InitView(Context context) {
this.mContext = context;
subjectList = DataContent.getSubjectList();
}
public View getView() {
View main_view = LayoutInflater.from(mContext).inflate(
R.layout.activity_main, null);
ll_main_content = (ViewGroup) main_view
.findViewById(R.id.ll_main_content);
for (Subject subject : subjectList) {
View cView = LayoutInflater.from(mContext).inflate(
R.layout.subject_item, null);
TextView tv_title = (TextView) cView.findViewById(R.id.tv_title);
tv_title.setText(subject.getSubTitle());
TextView tv_show_grade = (TextView) cView
.findViewById(R.id.tv_show_grade);
View view3 = cView.findViewById(R.id.ll_subhead);
for (Subhead subhead : subject.getSubheadList()) {
View view = LayoutInflater.from(mContext).inflate(
R.layout.subhead_item, null);
TextView tv_subtitle = (TextView) view
.findViewById(R.id.tv_subtext);
tv_subtitle.setText(subhead.getSubTitle());
LinearLayout ll_subhead = (LinearLayout) view
.findViewById(R.id.ll_item);
for (Item item : subhead.getItemList()) {
item.setTv_show_grade(tv_show_grade);
View view2 = LayoutInflater.from(mContext).inflate(
R.layout.item_item, null);
TextView tv_content = (TextView) view2
.findViewById(R.id.tv_content);
TextView tv_testtype = (TextView) view2
.findViewById(R.id.tv_testtype);
TextView tv_organization = (TextView) view2
.findViewById(R.id.tv_organization);
TextView tv_instruction = (TextView) view2
.findViewById(R.id.tv_instruction);
EditText et_deduct_points = (EditText) view2
.findViewById(R.id.et_deduct_points);
item.setmEditText(et_deduct_points);
item.setmTextView(tv_instruction);
et_deduct_points.setTag(item);
tv_content.setText(item.getContent());
tv_testtype.setText(item.getTestType());
tv_organization.setText(item.getOrganization());
tv_instruction
.setText((item.getInstruction() == null) ? "暂无(点击添加)"
: item.getInstruction());
et_deduct_points
.setText((item.getDeduct_points() == 0) ? ""
: String.valueOf(item.getDeduct_points()));
ll_subhead.addView(view2);
}
((ViewGroup) view3).addView(view);
}
tv_show_grade.setGravity(Gravity.CENTER);
if (subject.getSubTitle() != "日常监管检查") {
tv_show_grade
.setText("本项累计扣分:"
+ subject.getPoints()
+ " 得分:"
+ (subject.getTotalPoints() - subject
.getPoints()));
} else {
tv_show_grade.setText("本项累计扣分:" + subject.getPoints());
}
ll_main_content.addView(cView);
}
return main_view;
}
}
然后从MainAcitivty中加载该布局,从而实现了Excel样式的View。
小结一下:
1、想要做出这样的效果,对View的扩展性要想得很开,不能局限于屏幕的大小
2、类里用List集合去装载另一个类实现类与类之间的关系,用处很多,比如上述,比如Expandablelistview等等
3、循环List由内往外不断加载布局,实现动态加载布局
4、之所以每个类都对应去写一个xml,是因为如果不写,那就代表着你得在代码中手动new那些控件,写xml可以省略很多new new new
5、该方法也有缺陷,由于一次大量加载View,会导致开始会卡一段时间(正在想办法解决)
其实开始我是以一个Subject类去对应ListView的一个item,由于每个item大小不定,装载内容不一样,就不能使用ListView的重用View机制(也许是我还没深入理解吧),然后就会导致每换一个item都会卡一下。
其次,由于还需要定位,也就是根据Subject或者Subhead去准确定位,那么相比ScrollView比ListView好实现,因为每个Item高度都是wrap_content,在ListView中是无法提前知道其高度的(也可能是我不知道在哪得到item宽高吧),你们可以看看listView的滚动条,当item比较高时,滚动条就会变短,反之,则会变长,也就是listView只是单纯的用当前的item高度乘以item的个数来确实listView的整体高度的。而ScrollView则可以在加载完整个View后,在onLayout中得到每一个子View的高度,实现定位功能(重写ScrollVew)。
回到刚没有回答的问题,这里提到Adapter的getView方法。实现了这些功能后,让我感觉getView其实就是往父布局里加载一个一个的View,而重用View,就是不去实例化View,而是取得原来就已经实例化的View来改变里面控件的值(真是不想不知道,一想自己还差得远),而这次使用ScrollView来实现整个布局,就是差不多应用了getView的方式。
嗯,大概就是这些,说实话,做为理科生写文章还真是有点小累,表达能力太差,技术也不行,路还很长,万事开头难嘛,毕竟需要坚持。