美文网首页
左右上下联动滑动列表效果

左右上下联动滑动列表效果

作者: 刘孙猫咪 | 来源:发表于2017-12-23 16:22 被阅读0次
device-2017-12-23-155908.gif

上面这个是左右上下联动滑动列表效果,其实就是左边一个列表可以上下滑动,右边一个列表可以上下左右滑动,然后再将左边列表和右边列表关联起来。

这里上下滑动用的是ListView和ScrollView,左右滑动用的是ListView和HorizontalScrollView,ListView和ScrollView及HorizontalScrollView会有冲突,首先要解决它们之间的冲突,ListView和ScrollView一起使用会造成ListView显示不全,可以自定义ListView重写它的onMeasure方法,也可以计算ListView条目的总高度,将总高度设值给ListView,这里采用的是计算ListView条目的总高度,不过需要注意的是ListView条目的总高度这个方法在父布局是LinearLayout的时候才会有效;ListView和HorizontalScrollView冲突解决是自定义HorizontalScrollView的方式;

public class SyncHorizontalScrollView extends HorizontalScrollView {
    private View mView;
    public SyncHorizontalScrollView(Context context) {
        super(context);
    }

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

    public SyncHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);

        if(mView!=null) {
            mView.scrollTo(l, t);
        }
    }

    /**
     *
     * @param view
     */
    public void setScrollView(View view) {
        mView = view;
    }
}

接着去布局里面将控件摆放好,并给对应的列表设置适配器;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/farther_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <!-- 此部分是标题部分 -->

    <LinearLayout
        android:id="@+id/top_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:visibility="visible" >

        <!-- 左侧标题的父容器 -->

        <LinearLayout
            android:id="@+id/left_title_container"
            android:layout_width="@dimen/month_car_model_width"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <LinearLayout
                android:layout_width="@dimen/month_car_model_width"
                android:layout_height="@dimen/list_item_height"
                android:gravity="center"
                android:orientation="vertical" >

                <TextView
                    android:id="@+id/tv_car_model"
                    android:layout_width="@dimen/month_car_model_width"
                    android:layout_height="@dimen/list_item_height"
                    android:gravity="center"
                    android:maxLines="1"
                    android:text="data"
                    android:textSize="13sp" />
            </LinearLayout>

            <View style="@style/lineStyle"
                android:id="@+id/title_line"/>
        </LinearLayout>

        <!-- 右侧标题的父容器可实现水平滚动 -->

        <com.list.listapplication.com.list.listapplication.widget.SyncHorizontalScrollView
            android:id="@+id/title_horsv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:scrollbars="none" >

            <LinearLayout
                android:id="@+id/right_title_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical" >

                <LinearLayout
                    android:id="@+id/right_top_container"
                    android:layout_width="wrap_content"
                    android:layout_height="@dimen/list_item_height"
                    android:background="@color/white"
                    android:orientation="horizontal" >
                </LinearLayout>

                <View style="@style/lineStyle" />
            </LinearLayout>
        </com.list.listapplication.com.list.listapplication.widget.SyncHorizontalScrollView>
    </LinearLayout>

    <!-- 此部分是内容部分 用ScrollView实现上下滚动效果 -->

    <ScrollView
        android:id="@+id/car_scrollview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <!-- 左侧内容的父容器 -->

            <LinearLayout
                android:id="@+id/left_container"
                android:layout_width="@dimen/month_car_model_width"
                android:layout_height="match_parent"
                android:gravity="center_vertical"
                android:orientation="vertical"
                android:visibility="visible" >

                <ListView
                    android:id="@+id/left_container_listview"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >
                </ListView>
            </LinearLayout>

            <!-- 右侧内容的父容器 实现水平滚动 -->

            <com.list.listapplication.com.list.listapplication.widget.SyncHorizontalScrollView
                android:id="@+id/content_horsv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:scrollbars="none" >

                <LinearLayout
                    android:id="@+id/right_container"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center_vertical"
                    android:orientation="horizontal" >

                    <ListView
                        android:id="@+id/right_container_listview"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent" >
                    </ListView>
                </LinearLayout>
            </com.list.listapplication.com.list.listapplication.widget.SyncHorizontalScrollView>
        </LinearLayout>
    </ScrollView>

</LinearLayout>
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private LinearLayout leftContainerView, rightContainerView, rightTopContainer;
    private TextView tvCarModel;
    private ListView leftListView;
    private ListView rightListView;
    private SyncHorizontalScrollView titleHorsv;
    private SyncHorizontalScrollView contentHorsv;
    private MyLeftAdapter leftAdapter;
    private List<String> leftlList = new ArrayList<>();
    private MyRightAdapter myRightAdapter;
    private List<String> topList = new ArrayList<>();
    private Map<String, List<String>> rightMap = new HashMap<>();
    private int screenW;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取屏幕的宽度
        screenW = DensityUtil.getW(MainActivity.this);
        rightTopContainer = (LinearLayout) findViewById(R.id.right_top_container);
        pasentData();
        initView();
    }

    private void initView() {
        tvCarModel = (TextView) findViewById(R.id.tv_car_model);

        tvCarModel.setTextSize(TypedValue.COMPLEX_UNIT_PX, DensityUtil.sp2px(MainActivity.this, 13f));

        leftContainerView = (LinearLayout) findViewById(R.id.left_container);
        //左边列表
        leftListView = (ListView) findViewById(R.id.left_container_listview);
        leftListView.setDivider(null);

        rightContainerView = (LinearLayout) findViewById(R.id.right_container);
        //右边列表
        rightListView = (ListView) findViewById(R.id.right_container_listview);
        rightListView.setDivider(null);

        titleHorsv = (SyncHorizontalScrollView) findViewById(R.id.title_horsv);
        contentHorsv = (SyncHorizontalScrollView) findViewById(R.id.content_horsv);

        // 设置两个水平控件的联动
        titleHorsv.setScrollView(contentHorsv);
        contentHorsv.setScrollView(titleHorsv);

        // 添加左边内容数据
        leftContainerView.setBackgroundColor(Color.WHITE);
        //左边列表数据适配器
        leftAdapter = new MyLeftAdapter(MainActivity.this, leftlList);
        leftListView.setAdapter(leftAdapter);

        // 添加右边内容数据
        rightContainerView.setBackgroundColor(Color.WHITE);

        myRightAdapter = new MyRightAdapter(this, rightMap, topList, leftlList);
        rightListView.setAdapter(myRightAdapter);
        //设置左边和右边listview的高度
        DensityUtil.setListViewHeightBasedOnChildren(rightListView);
        DensityUtil.setListViewHeightBasedOnChildren(leftListView);
    }

    /**
     * 根据组数据的多少创建textview
     */
    private void getTextView() {
        for (int i = 0; i < topList.size(); i++) {
            TextView tv = new TextView(MainActivity.this);
            tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, DensityUtil.sp2px(MainActivity.this, 13f));
            tv.setGravity(Gravity.CENTER);// //此处相当于布局文件中的Android:gravity属性
            tv.setTextColor(Color.parseColor("#000000"));
            tv.setText("" + topList.get(i));
            int w = 0;
            if (topList.size() >= 4) {
                w = DensityUtil.dip2px(MainActivity.this, 65);
            } else {
                w = (screenW - DensityUtil.dip2px(MainActivity.this, 80)) / topList.size();
            }
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(w, LinearLayout.LayoutParams.MATCH_PARENT);
            tv.setLayoutParams(params);// 设置圆点的大小
            rightTopContainer.addView(tv);
        }
    }


    /**
     * 解析json数据
     */
    private void pasentData() {
        String readAssetsFile = readAssetsFile(MainActivity.this, "data/data.txt");
        List<Object> objects = parseMonthSale(readAssetsFile);
        if (objects != null && objects.size() != 0) {
            DataInfo object = (DataInfo) objects.get(0);
            List<String> groupList = object.groupList;
            if (groupList == null)
                groupList = new ArrayList<>();
            topList.addAll(groupList);
            List<DataInfo> saleList = object.saleList;
            if (saleList == null) {
                saleList = new ArrayList<>();
            }
            if (saleList != null && saleList.size() != 0) {
                for (int i = 0; i < saleList.size(); i++) {
                    DataInfo dtGzsHome = saleList.get(i);
                    String data_type = dtGzsHome.data_type;
                    leftlList.add(data_type);
                    List<String> dataList = dtGzsHome.dataList;
                    if (dataList == null) {
                        dataList = new ArrayList<>();
                    }
                    rightMap.put(data_type, dataList);
                }
            }
        }
        System.out.println("---------rightMap" + rightMap.size());
        if (topList.size() != 0) {
            // 根据组数据的多少创建textview
            getTextView();
        }
    }

    /**
     * 获取程序中Assets文件底下的文件txt
     *
     * @param context  上下文
     * @param fileName 文件名称
     * @return txt文本的字符串
     */
    private String readAssetsFile(Context context, String fileName) {
        String res = "";
        try {
            // 得到资源中的asset数据流
            InputStream in = context.getResources().getAssets().open(fileName);
            res = readTextFromSDcard(in);
        } catch (Exception e) {
            Log.e(TAG, "");
        }
        return res;
    }

    /**
     * 按行读取txt
     *
     * @param is
     * @return
     * @throws Exception
     */
    private String readTextFromSDcard(InputStream is) throws Exception {
        InputStreamReader reader = new InputStreamReader(is);
        BufferedReader bufferedReader = new BufferedReader(reader);
        StringBuffer buffer = new StringBuffer("");
        String str;
        while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
            buffer.append("\n");
        }
        return buffer.toString();
    }

    private static List<Object> parseMonthSale(String data) {
        List<Object> list = new ArrayList<Object>();
        try {
            DataInfo info = new DataInfo();
            JSONObject itemJo = new JSONObject(data);
            JSONObject json = itemJo.getJSONObject("success");

            info.groupList = new ArrayList<String>();
            boolean null3 = json.isNull("group_list");
            if (!null3) {
                JSONArray group_list = json.getJSONArray("group_list");
                for (int i = 0; i < group_list.length(); i++) {
                    String string = group_list.getString(i);
                    info.groupList.add(string);
                }
            }

            info.saleList = new ArrayList<DataInfo>();
            boolean null1 = json.isNull("datas");
            if (!null1) {
                JSONArray dataArray = json.getJSONArray("datas");
                for (int i = 0; i < dataArray.length(); i++) {
                    JSONObject jsonObject = dataArray.getJSONObject(i);
                    DataInfo vo = new DataInfo();
                    vo.CLASSES_ID = parseString("CLASSES_ID", jsonObject);
                    vo.data_type = parseString("data_type", jsonObject);
                    vo.dataList = new ArrayList<String>();
                    boolean null2 = jsonObject.isNull("group_datas");
                    if (!null2) {
                        JSONArray array = jsonObject.getJSONArray("group_datas");
                        for (int j = 0; j < array.length(); j++) {
                            String object = (String) array.getString(j);
                            vo.dataList.add(object);
                        }
                    }
                    info.saleList.add(vo);
                }
            }
            list.add(info);
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
        return list;
    }

    public static String parseString(String key, JSONObject json) {
        if (json.isNull(key)) {
            return "";
        } else {
            try {
                return json.getString(key);
            } catch (JSONException e) {
                e.printStackTrace();
                return "";
            }
        }
    }
}

左边ListView的adapter

public class MyLeftAdapter extends BaseAdapter{

    private Context context;
    private List<String> list;

    public MyLeftAdapter(Context context, List<String> list) {
        super();
        this.context = context;
        this.list = new ArrayList<String>();
        if(list!=null)
        {
            this.list.addAll(list);
        }
    }

    public void nodfiyData(List<String> list){
        if(list!=null)
        {
            this.list.clear();
            this.list.addAll(list);
        }
        notifyDataSetChanged();
    }
    @Override
    public int getCount() {
        if (list!=null) {
            return list.size();
        }
        return 0;
    }

    @Override
    public Object getItem(int position) {
        if (list!=null) {
            return list.get(position);
        }
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHold hold;
        if (convertView==null) {
            hold=new ViewHold();
            convertView= LayoutInflater.from(context).inflate(R.layout.month_carmodel_left_item, null);
            hold.textView=(TextView) convertView.findViewById(R.id.left_container_textview0);
            hold.textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, DensityUtil.sp2px(context,13f));
            convertView.setTag(hold);
        }else {
            hold=(ViewHold) convertView.getTag();
        }
        String string = list.get(position);
        hold.textView.setText(""+string);
        return convertView;
    }

    static class ViewHold{
        TextView textView;
    }
}

因为右边列表数据是动态变化的,所以右边item布局需要动态创建,根据实际获取到的数据进行创建;

public class MyRightAdapter extends BaseAdapter{
    private Context context;
    private List<String> grouplist;
    private List<String> leftList;
    private Map<String,List<String>> rightMap;
    private int timeSum=0;
    public MyRightAdapter(Context context, Map<String,List<String>> rightMap, List<String> grouplist, List<String> leftList) {
        super();
        this.context = context;
        this.grouplist=grouplist;
        this.leftList=leftList;
        this.rightMap = new HashMap<String,List<String>>();
        if(rightMap!=null)
        {
            this.rightMap.putAll(rightMap);
        }
    }
    public void nodfiyData(Map<String,List<String>> rightMap){
        if(rightMap!=null)
        {
            this.rightMap.clear();
            this.rightMap.putAll(rightMap);
        }
        notifyDataSetChanged();
    }
    @Override
    public int getCount() {
        if (rightMap!=null) {
            return rightMap.size();
        }
        return 0;
    }

    @Override
    public Object getItem(int position) {
        if (rightMap!=null) {
            return rightMap.get(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.layout_right_item, null);
            holder.right_layout=(LinearLayout) convertView.findViewById(R.id.right_layout);
            for (int i = 0; i < grouplist.size(); i++) {
                long start = System.currentTimeMillis();
                TextView tv = new TextView(context);
                tv.setTextSize(TypedValue.COMPLEX_UNIT_PX,DensityUtil.sp2px(context,13f));
                tv.setGravity(Gravity.CENTER);// //此处相当于布局文件中的Android:gravity属性
                tv.setTextColor(context.getResources().getColor(R.color.black));

                String string = leftList.get(position);
                List<String> list = rightMap.get(string);
                String string2 = list.get(i);
                if (string2==null||string2.length()==0) {
                    string2="0";
                }
                tv.setText("" +string2 );
                int w=0;
                if (grouplist.size()>=4) {
                    w= DensityUtil.dip2px(context,65);
                }else{
                    w=(DensityUtil.getW(context)-DensityUtil.dip2px(context,80))/grouplist.size();
                }
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(w,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                tv.setLayoutParams(params);
                holder.right_layout.addView(tv);
                long end = System.currentTimeMillis();
                long time = end - start;
                timeSum+=time;
            }
            convertView.setTag(holder);
        }else{
            holder=(ViewHolder) convertView.getTag();
        }

        System.out.println("--------------timeSum" + timeSum);// 5002   5244  154  117  212
        return convertView;
    }
    class ViewHolder{
        LinearLayout right_layout;
    }
}

源码地址:
https://pan.baidu.com/s/1boP8q9D

相关文章

网友评论

      本文标题:左右上下联动滑动列表效果

      本文链接:https://www.haomeiwen.com/subject/dzdqgxtx.html