Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 頭行列可固定的表格制作

android 頭行列可固定的表格制作

編輯:關於Android編程

1、概述

在android中我們平日經常用listview、gridview控件來制作數據不固定的表格,一般都是頭列表格頭固定,底下listview展示可變數據,然而在工作中我碰到了一個需求:上下滑動時頭列固定,左右滑動時頭行固定的,流量了很多網站都沒有找到合適的,於是自己想了一個解決方案。

馬上上效果圖,有這個效果需要的同仁繼續往下看

\

 

2、思路

我們看到的效果好像是一個既可以左右滑動又能上下滑動的ListView,其實不然,這個要用單純的一個ListView或者ScrollView實現非常困難,所以我選擇了把它們組合起來,組合方式如下:

\

最左上角的TextView是不動的,當左右滑動時候,第一列固定,右邊上下兩個ScrollView實現聯動;當上下滑動時,頭部第一行不動,下面兩個ListView實現聯動就行了。

3、代碼實現

首先是主界面的布局:avtivity_main




    

    

    

        
            
            

            

            

            

            

            

            

            

            

            

            
            
        
    

    

    

    

        
    


由於頭部標題的ScrollView一般是不能去主動滑動的,所以要攔截掉ScrollView的touch事件,代碼詳細大家都懂,這裡為了方便一並附出:

 

 

package com.lunge.mydifdirtable.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;

/**
 * Created by Binglun on 7/13 0013 17:26
 */
public class NoScrollHorizontalScrollView extends HorizontalScrollView {
    public NoScrollHorizontalScrollView(Context context) {
        super(context);
    }

    public NoScrollHorizontalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NoScrollHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptHoverEvent(MotionEvent event) {
        return false;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return false;
    }
}
看到這裡,大家就明白當左右滑動時,是下面的ScrollView帶著上面的ScrollView一起滑動的,實現方式是再自定義一個ScrollView,用監聽者模式,在自己滑動的回調代碼裡onScrollStateChange,調用頂部ScrollView的onScroll方法,實現同步滑動;代碼如下:

 

 

package com.lunge.mydifdirtable.view;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.HorizontalScrollView;

/**
 * Created by Lunger on 7/11 0011 15:47
 */
public class LinkedHorizontalScrollView extends HorizontalScrollView {
    private LinkScrollChangeListener listener;
    public LinkedHorizontalScrollView(Context context) {
        super(context);
    }

    public LinkedHorizontalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public LinkedHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    public void setMyScrollChangeListener(LinkScrollChangeListener listener){
        this.listener = listener;
    }
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if(null != listener)
        listener.onscroll(this, l, t, oldl, oldt);
    }
    /**
     * 控制滑動速度
     */
    @Override
    public void fling(int velocityY) {
        super.fling(velocityY / 2);
    }
   public  interface LinkScrollChangeListener {
        void onscroll(LinkedHorizontalScrollView view, int l, int t, int oldl, int oldt);
    }
}

控件都已經介紹完了,接下來就是主界面的程序:

 

 

package com.lunge.mydifdirtable;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AbsListView;
import android.widget.HorizontalScrollView;
import android.widget.ListView;

import com.lunge.mydifdirtable.adapter.LvInfoAdapter;
import com.lunge.mydifdirtable.adapter.LvNameAdapter;
import com.lunge.mydifdirtable.view.LinkedHorizontalScrollView;
import com.lunge.mydifdirtable.view.NoScrollHorizontalScrollView;

public class MainActivity extends AppCompatActivity {

    private NoScrollHorizontalScrollView sv_normalgoods_title;//不可滑動的頂部左側的ScrollView
    private LinkedHorizontalScrollView sv_normalgoods_detail;//底部左側的ScrollView
    private ListView lv_normalgoodname;//底部左側的ListView
    private ListView lv_normalgood_info;//底部右側的ListView

    boolean isLeftListEnabled = false;
    boolean isRightListEnabled = false;

    private LvNameAdapter mLvNormalNameAdapter;
    private LvInfoAdapter mLvNormalInfoAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initAdapter();
    }


    private void initView() {
        sv_normalgoods_title = (NoScrollHorizontalScrollView)findViewById(R.id.sv_title);
        sv_normalgoods_detail = (LinkedHorizontalScrollView)findViewById(R.id.sv_good_detail);
        lv_normalgoodname = (ListView) findViewById(R.id.lv_goodname);
        lv_normalgood_info = (ListView)findViewById(R.id.lv_good_info);
        combination(lv_normalgoodname, lv_normalgood_info, sv_normalgoods_title, sv_normalgoods_detail);
    }

    private void initAdapter() {
        mLvNormalNameAdapter = new LvNameAdapter(this);
        mLvNormalInfoAdapter = new LvInfoAdapter(this);
        lv_normalgoodname.setAdapter(mLvNormalNameAdapter);
        lv_normalgood_info.setAdapter(mLvNormalInfoAdapter);
    }

    private void combination(final ListView lvName, final ListView lvDetail, final HorizontalScrollView title, LinkedHorizontalScrollView content) {
        /**
         * 左右滑動同步
         */
        content.setMyScrollChangeListener(new LinkedHorizontalScrollView.LinkScrollChangeListener() {
            @Override
            public void onscroll(LinkedHorizontalScrollView view, int x, int y, int oldx, int oldy) {
                title.scrollTo(x, y);
            }
        });

        /**
         * 上下滑動同步
         */
        // 禁止快速滑動
        lvName.setOverScrollMode(ListView.OVER_SCROLL_NEVER);
        lvDetail.setOverScrollMode(ListView.OVER_SCROLL_NEVER);
        //左側ListView滾動時,控制右側ListView滾動
        lvName.setOnScrollListener(new AbsListView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                //這兩個enable標志位是為了避免死循環
                if (scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                    isRightListEnabled = false;
                    isLeftListEnabled = true;
                } else if (scrollState == SCROLL_STATE_IDLE) {
                    isRightListEnabled = true;
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                                 int totalItemCount) {
                View child = view.getChildAt(0);
                if (child != null && isLeftListEnabled) {
                    lvDetail.setSelectionFromTop(firstVisibleItem, child.getTop());
                }
            }
        });

        //右側ListView滾動時,控制左側ListView滾動
        lvDetail.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if (scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                    isLeftListEnabled = false;
                    isRightListEnabled = true;
                } else if (scrollState == SCROLL_STATE_IDLE) {
                    isLeftListEnabled = true;
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                                 int totalItemCount) {
                View c = view.getChildAt(0);
                if (c != null && isRightListEnabled) {
                    lvName.setSelectionFromTop(firstVisibleItem, c.getTop());
                }
            }
        });

    }
}
代碼不多也比較容易理解,這裡就不多述。就介紹到此;

 

等等,博主,裡面的adapter代碼呢???

這也要附啊,好吧:

LvNameAdapter:

 

package com.lunge.mydifdirtable.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.lunge.mydifdirtable.R;


/**
 * Created by Binglun on 7/13 0013 16:05
 */
public class LvNameAdapter extends BaseAdapter {
    private Context context;

    public LvNameAdapter(Context context) {
        this.context = context;
    }

    @Override
    public int getCount() {
        return 100;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if(convertView == null){
            holder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.item_lv_good_name, null);
            holder.tv_goodname = (TextView) convertView.findViewById(R.id.tv_name);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }
        holder.tv_goodname.setText("iPone" + (position+4) + "s");
        return convertView;
    }
    class ViewHolder{
        TextView tv_goodname;
    }
}
對應布局文件:


    

 

LvInfoAdapter:

 

package com.lunge.mydifdirtable.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.lunge.mydifdirtable.R;


/**
 * Created by Lunger on 7/13 0013 16:06
 */
public class LvInfoAdapter extends BaseAdapter {
    private Context context;

    public LvInfoAdapter(Context context) {
        this.context = context;
    }

    @Override
    public int getCount() {
        return 100;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.item_lv_good_info, null);
            holder.tv_barcode = (TextView) convertView.findViewById(R.id.tv_barcode);
            holder.tv_category = (TextView) convertView.findViewById(R.id.tv_category);
            holder.tv_spec = (TextView) convertView.findViewById(R.id.tv_spec);
            holder.tv_unit = (TextView) convertView.findViewById(R.id.tv_unit);
            holder.tv_supplyer = (TextView) convertView.findViewById(R.id.tv_supplyer);
            holder.tv_sale_money = (TextView) convertView.findViewById(R.id.tv_sale_money);
            holder.tv_income_money = (TextView) convertView.findViewById(R.id.tv_income_money);
            holder.tv_keep = (TextView) convertView.findViewById(R.id.tv_keep);
            holder.tv_intime = (TextView) convertView.findViewById(R.id.tv_intime);
            holder.tv_online = (ImageView) convertView.findViewById(R.id.iv_online);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        if (position < 10) {
            holder.tv_barcode.setText("1001200660" + position);
        } else {
            holder.tv_barcode.setText("100120066" + position);
        }
        holder.tv_category.setText("類型" + position);
        holder.tv_spec.setText("規格" + position);
        holder.tv_unit.setText("個");
        holder.tv_supplyer.setText("供應商" + position);
        holder.tv_sale_money.setText("價格" + position);
        holder.tv_keep.setText("1年");
        holder.tv_intime.setText("2016-03-21");
        holder.tv_income_money.setText("進貨價" + position);

        return convertView;
    }
}

class ViewHolder {
    TextView tv_barcode;
    TextView tv_category;
    TextView tv_spec;
    TextView tv_unit;
    TextView tv_supplyer;
    TextView tv_sale_money;
    TextView tv_income_money;
    TextView tv_keep;
    TextView tv_intime;
    ImageView tv_online;

}
對應布局文件:





    

    

    

    

    

    

    

    

    

    

    

        

    
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved