仿QuickOffice的Excel的表格实现

前一段时间做了一个移动办公阅读App,学到了挺多东西,现在把Excel的表格实现跟大家分享一下

首先看看布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MyTable" >

    <TextView 
        android:id="@+id/blank_tv"
        android:layout_width="35dp"
        android:layout_height="35px"
        android:background="@drawable/top02"/>
    
    
   <com.example.mytable.CustomHScrollView  
        android:id="@+id/row_scroll"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:layout_toRightOf="@id/blank_tv"
        android:scrollbars="none"
        android:overScrollMode="always">
        <LinearLayout 
            android:layout_width="wrap_content"
            android:layout_height="match_parent">
            <TableLayout
		        android:id="@+id/row_head_tab"
				android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
				android:stretchColumns="*">
		    </TableLayout>
        </LinearLayout>
    </com.example.mytable.CustomHScrollView >
     
    
    <com.example.mytable.CustomScrollView 
        android:id="@+id/line_scroll"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/blank_tv"
        android:background="@color/white"
        android:scrollbars="none"
        android:overScrollMode="always">
        <LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TableLayout
        		android:id="@+id/line_head_tab"
		        android:layout_width="35dp"
		        android:layout_height="match_parent"
		        android:stretchColumns="*">
    		</TableLayout>
        </LinearLayout>
    </com.example.mytable.CustomScrollView>
    
 
     <com.example.mytable.CustomHScrollView 
         android:id="@+id/view_h_scroll"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@id/row_scroll"
         android:layout_toRightOf="@id/line_scroll"
         android:background="@color/white"
         android:scrollbars="none"
         android:overScrollMode="always">
         <com.example.mytable.CustomScrollView 
             android:id="@+id/view_v_scroll" 
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:scrollbars="none">
             <LinearLayout
		         android:layout_width="match_parent"
		         android:layout_height="wrap_content" >
		         <TableLayout
			        android:id="@+id/tablelayout"
			        android:layout_width="wrap_content"
			        android:layout_height="wrap_content"
			        android:stretchColumns="*" 
			        android:orientation="vertical">
			     </TableLayout>
        	</LinearLayout>
         </com.example.mytable.CustomScrollView >
     </com.example.mytable.CustomHScrollView>
     
</RelativeLayout>

可以看到,第一个TextView是一个空白的TextView,它什么都不做,就是表格左上角用来连接行号和列号的而已。
然后,我用了四个滚动视图,一个水平滚动视图用来表示列号,一个垂直滚动视图表示行号,另外一个垂直和水平视图相互嵌套,用来展示Excel的数据,在每个ScrollView里面,我用了TableLayout,它能将以一行一行的形式呈现。此外,我用到了自定义的滚动视图,接下来我们会看到它的作用

我们先看看是怎么往表格中添加数据的
<@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.my_table);
		
		//初始化视图
		addToLineHead(MIN_LINE_NUM);
		addToRowHead(MIN_ROW_NUM);
		addToView(MIN_ROW_NUM, MIN_LINE_NUM);
			
		//绑定视图,同步
		synScrollViews();
	}

我们调用了四个函数,他们分别往视图里面添加了行号,列号和模拟的Excel数据,并将视图绑定(后面介绍),这里,我只说明addToView()函数,它将Excel的模拟数据添加到了视图当中,添加列号和行号同理,请看

    /**
     * @param number 添加的行,列的数量
     * 往视图中添加数据
     */
    public void addToView(int rowNum, int lineNum)
    {
    	mTable = (TableLayout)findViewById(R.id.tablelayout);              //获得视图中的table
    	mTable.setStretchAllColumns(true);
    	
    	TableLayout.LayoutParams tableLparams = new TableLayout.LayoutParams(
				TableLayout.LayoutParams.WRAP_CONTENT,
				TableLayout.LayoutParams.WRAP_CONTENT);
    	tableLparams.setMargins(0, 0, 0, 0); 
    	 	   	
    	mViewEt = new MyTextView(this);
    	
    	//设置TextView的各个属性
    	mViewEt.setLayoutParams(new android.widget.TableRow.LayoutParams(DEFAULT_WIDTH, 
				DEFAULT_HEIGHT));							
		mViewEt.setBackgroundResource(R.drawable.my_textview);
		mViewEt.setGravity(Gravity.CENTER);
		mViewEt.setTextSize(TEXT_SIZE);                           //字体大小
		mViewEt.setTextColor(Color.parseColor("#095583"));       //文本颜色
	

		
    	//行
    	for(int i=1; i <= lineNum; ++i)
    	{
    		TableRow tablerow = new TableRow(ExcelTable.this);

    		//列
    		for(int j=1; j <= rowNum; ++j)
        	{
        		
    			MyTextView cloneViewTv = mViewEt.clone();      //关键点
    			cloneViewTv.setText(String.valueOf(i*j));
                        tablerow.addView(cloneViewTv);                 //将这个TextView添加到表格中的行

        	}
    		mTable.addView(tablerow, tableLparams);
    		
    	}
    }

这个函数先是获取了在滚动视图中的TableLayout,接着,我们又获得了Table的Row,它代表Table的一行,然后我们就可以将TextView添加到这个Row中了,再把这一行添加到Table里,一行一行的添加,就形成了Excel似的表格,上面,我用了自定义的TextView,它实现了 克隆方法,这是很 关键的一点,因为它大大提高了Excel表格打开的速度,不然假如要生成的Excel单元格(也就是TextView)过多的话,它要花去极大的时间去初始化生成各个TextView,看看MyTextView的代码
public class MyTextView extends TextView implements Cloneable{

	
	public MyTextView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	public MyTextView clone()
	{
		MyTextView editText = null;
		try
		{
			editText = (MyTextView)super.clone();			
		}
		catch (CloneNotSupportedException e)
		{
			e.printStackTrace();
		}
		return editText;
		
	}

}

接下来,我们要实现列号的水平ScrollView和显示数据的水平ScrollView同步滚动,垂直的 ScrollView和显示数据的垂直ScrollView同步滚动
/**
     * 绑定视图同步显示
     */
    private void synScrollViews()
    {
    	mHRowHeadScrollView = (CustomHScrollView)findViewById(R.id.row_scroll);
    	mHViewScroll = (CustomHScrollView)findViewById(R.id.view_h_scroll);
    	mLineScrollView = (CustomScrollView)findViewById(R.id.line_scroll);
    	mViewScroll = (CustomScrollView)findViewById(R.id.view_v_scroll);
    	   	
    	//绑定
    	mHRowHeadScrollView.setScrollView(mHViewScroll);
    	mHViewScroll.setScrollView(mHRowHeadScrollView);
    	mLineScrollView.setScrollView(mViewScroll);
    	mViewScroll.setScrollView(mLineScrollView);
    }

setScrollView()是自定义的方法,这也是要自定义ScrollView的原因之一,看看代码

/**
   	 * @param view
   	 * 实现同步显示
   	 */
   	public void setScrollView(View view)
   	{  
   		 mView = view;    
   	}

很简单,就是在ScrollView里面定义了一个View,然后传递引用,这有什么用呢?当我们滑动ScrollView的时候,ScrollView会自动调用onScrollChanged(int l, int t, int oldl, int oldt)方法,所以,当我们滑动一个ScrollView的时候,只需要在这个函数里面处理绑定的视图的滑动就可以了,请看

        protected void onScrollChanged(int l, int t, int oldl, int oldt)
   	{    
   		 super.onScrollChanged(l, t, oldl, oldt);    
   		 if(mView!=null)
   		 {  
   		    mView.scrollTo(l, t);  <span style="white-space:pre">					</span>//滚动到相应的点
   		 }    
   		 
   	} 

这样,就实现了视图之间的同步滚动了。但是,还有一个问题,两个ScrollView嵌套的时候,用手滑动的时候,这个滑动事件是先给水平的ScrollView呢?还是先给垂直的ScrollView呢?这势必会造成混乱,所以必须要处理一下

       public CustomScrollView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		mGestureDetector = new GestureDetector(new VScrollDetector()); 
	        setFadingEdgeLength(0); 
	}
         @Override
	 public boolean onInterceptTouchEvent(MotionEvent ev) {                                       //拦截事件
	     return super.onInterceptTouchEvent(ev) && mGestureDetector.onTouchEvent(ev); 
	 } 
	  
	  // 返回失败如果我们的手势是横向滑动  
	 class VScrollDetector extends SimpleOnGestureListener { 
	        @Override
	    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {   	
	         if(Math.abs(distanceY) > Math.abs(distanceX)) {                                      //如果手势垂直滑动的距离大于水平滑动的距离
	                return true; 
	         } 
	        	
	         return false; 
	    } 
	 }

通过在ScrollView自定义一个手势,拦截事件,并水平和垂直滑动的距离,来得出应该往哪个方向滑动,这样一个Excel的表格就差不多能用了。当然,这个方法还是有很多不足之处,希望大神们指教!

GitHub源码地址:Https://github.com/CatMHW






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值