View篇——实现Excel表格显示

第一次发表博客,难免寒暄几句。见谅

学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>


subhead_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="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>


item_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="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,会导致开始会卡一段时间(正在想办法解决)


刚提到开始是用ListView装载的,为何改成这样呢?

其实开始我是以一个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的方式。

嗯,大概就是这些,说实话,做为理科生写文章还真是有点小累,表达能力太差,技术也不行,路还很长,万事开头难嘛,毕竟需要坚持。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值