2019-05-15 18:50:41 SageDeceiveFiend 阅读数 66
  • Android 高级专题

    本课程包含23章,共计95个小节课程,内容包括:Android多线程、网络编程、数据解析、数据存储、多媒体、Android 图形图像、Android 动画、GPS 定位、 Android 传感器编程、蓝牙、NDK、消息推送、二维码生成与扫描、分享和第三方登录、Bmob云服务、Afinal框架、 XUtils框架、版本控制、性能测试(听云)、App发布上线、Vitamio 跨平台播放器、EventBus、Android MVP 架构等。

    10602 人正在学习 去看看 郭宏志

Android二级采样

二级采样

需要寻找工具类的请访问https://blog.csdn.net/SageDeceiveFiend/article/details/90215498三级缓存部分!

	什么是二级采样 二级采样是一种对图片进行压缩的技术 原理就是对图片边框进行比
	例的缩小再对图片像素点进行等比例的缩小最后形成一张新的图片这样就叫做二级采样

在这里插入图片描述
下面的图为原图 上面顶部的图为二级采样后的图片

// An highlighted block
public class MainActivity extends AppCompatActivity {

    ImageView img;
    ImageView imgimg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        img=findViewById(R.id.img);
        imgimg=findViewById(R.id.imgimg);

        try {
            byte[] bytes = new MyAsnatask().execute("http://www.dv37.com/upload/editor/201804/1524894535_871992.jpg").get();
//第一次采样:只采边框 计算压缩比例          
            BitmapFactory.Options options = new BitmapFactory.Options();
           //设置只采边框
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            int width = options.outWidth;
            int height = options.outHeight;
//计算缩放比例
            int size = 2;
            while (width / size > 400 || height / size > 400) {
                size *= 2;
            }
            设置只采边框为fasle
            options.inJustDecodeBounds=false;
            //设置缩放比例
            options.inSampleSize=size;

         Bitmap bitmap1=   BitmapFactory.decodeByteArray(bytes,0,bytes.length);

            Bitmap bitmap=BitmapFactory.decodeByteArray(bytes,0,bytes.length,options);//采样

            img.setImageBitmap(bitmap);
            imgimg.setImageBitmap(bitmap1);

        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }
}

2016-03-07 15:50:10 menglele1314 阅读数 1656
  • Android 高级专题

    本课程包含23章,共计95个小节课程,内容包括:Android多线程、网络编程、数据解析、数据存储、多媒体、Android 图形图像、Android 动画、GPS 定位、 Android 传感器编程、蓝牙、NDK、消息推送、二维码生成与扫描、分享和第三方登录、Bmob云服务、Afinal框架、 XUtils框架、版本控制、性能测试(听云)、App发布上线、Vitamio 跨平台播放器、EventBus、Android MVP 架构等。

    10602 人正在学习 去看看 郭宏志

android BaseExpandableListAdapter 二级菜单适配器

activity_main.xml

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

    <ExpandableListView
        android:id="@+id/home_a_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/ll_title"
        android:childDivider="#EEEEEE"
        android:divider="#c8c7cc"
        android:dividerHeight="1dp"
        android:gravity="center"
        android:groupIndicator="@null"
        android:listSelector="#00000000" />

</RelativeLayout>
MainActivity.java
package com.zcycjy.mobile.fragment;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupExpandListener;

import com.zcycjy.mobile.R;
import com.zcycjy.mobile.adapter.ExpandableAdapter;
import com.zcycjy.mobile.entity.HomeType;

/**
 * @author itps
 * 
 */
public class MainActivity extends Activity {

	// 标题
	private List<String> groupArray = new ArrayList<String>();
	// 子标题
	private List<List<HomeType>> childArray = new ArrayList<List<HomeType>>();
	private ExpandableAdapter adapters;
	private ExpandableListView expandableListView;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		getDatas(0);
		
		initView();
	}

	private void initView() {
		expandableListView = (ExpandableListView)findViewById(R.id.home_a_list);
		adapters = new ExpandableAdapter(this, groupArray, childArray);
		expandableListView.setAdapter(adapters);

		expandableListView.setOnChildClickListener(new OnChildClickListener() {

			@Override
			public boolean onChildClick(ExpandableListView parent, View v,
					int groupPosition, int childPosition, long id) {
				// TODO Auto-generated method stub
				HomeType ht = (HomeType) adapters.getChild(groupPosition,
						childPosition);
				return false;
			}
		});
		expandableListView
				.setOnGroupExpandListener(new OnGroupExpandListener() {

					@Override
					public void onGroupExpand(int groupPosition) {
						for (int i = 0; i < groupArray.size(); i++) {
							if (groupPosition != i) {
								expandableListView.collapseGroup(i);
							}
						}
					}
				});
	}

	private void getDatas(int type) {
		// 会计
		groupArray.add("注册会计师");
		List<HomeType> ta1 = new ArrayList<HomeType>();
		ta1.add(new HomeType("会计", "000001"));
		ta1.add(new HomeType("审计", "000002"));
		ta1.add(new HomeType("财务成本管理", "000003"));
		ta1.add(new HomeType("税法", "000004"));
		ta1.add(new HomeType("经济法", "000005"));
		ta1.add(new HomeType("公司战略与风险管理", "000006"));
		groupArray.add("高级会计职称");
		List<HomeType> ta2 = new ArrayList<HomeType>();
		ta2.add(new HomeType("高级会计实务", "000011"));
		groupArray.add("中级会计职称");
		List<HomeType> ta3 = new ArrayList<HomeType>();
		ta3.add(new HomeType("中级会计实务", "000021"));
		ta3.add(new HomeType("中级经济法", "000022"));
		ta3.add(new HomeType("中级财务管理", "000023"));

		childArray.add(ta1);
		childArray.add(ta2);
		childArray.add(ta3);
	}

}
ExpandableAdapter.java
package com.zcycjy.mobile.adapter;

import java.util.List;

import com.zcycjy.mobile.entity.HomeType;

import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;

public class ExpandableAdapter extends BaseExpandableListAdapter {

	private List<String> groupArray;
	private List<List<HomeType>> childArray;
	private Activity activity;

	public ExpandableAdapter(Activity act, List<String> groupArray,
			List<List<HomeType>> childArray) {
		this.activity = act;
		this.groupArray = groupArray;
		this.childArray = childArray;
	}

	@Override
	public Object getChild(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return childArray.get(groupPosition).get(childPosition);
	}

	@Override
	public long getChildId(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return childPosition;
	}

	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean isLastChild, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		String string = childArray.get(groupPosition).get(childPosition)
				.getTypeName();
		return getGenericView(string, 1);
	}

	@Override
	public int getChildrenCount(int groupPosition) {
		// TODO Auto-generated method stub
		return childArray == null ? 0 : childArray.get(groupPosition).size();
	}

	@Override
	public Object getGroup(int groupPosition) {
		// TODO Auto-generated method stub
		return groupArray.get(groupPosition);
	}

	@Override
	public int getGroupCount() {
		// TODO Auto-generated method stub
		return groupArray == null ? 0 : groupArray.size();
	}

	@Override
	public long getGroupId(int groupPosition) {
		// TODO Auto-generated method stub
		return groupPosition;
	}

	@Override
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		String string = groupArray.get(groupPosition);
		return getGenericView(string, 0);
	}

	@Override
	public boolean hasStableIds() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return true;
	}

	/**
	 * Children 's View
	 * 
	 * @param string
	 * @return
	 */
	public TextView getGenericView(String string, int i) {
		AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(
				ViewGroup.LayoutParams.MATCH_PARENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		TextView text = new TextView(activity);
		text.setLayoutParams(layoutParams);
		// Center the text vertically
		text.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
		// Set the text starting position
		if (i == 1) {
			text.setTextColor(Color.parseColor("#000000"));
			text.setPadding(70, 10, 0, 10);
			text.setText(string + " >>>");
		} else {
			text.setTextColor(Color.parseColor("#F39801"));
			text.setPadding(40, 20, 0, 20);
			text.setText(string + " ▼▼▼");
		}
		return text;
	}
}





2017-04-18 15:05:24 yuhys 阅读数 20074
  • Android 高级专题

    本课程包含23章,共计95个小节课程,内容包括:Android多线程、网络编程、数据解析、数据存储、多媒体、Android 图形图像、Android 动画、GPS 定位、 Android 传感器编程、蓝牙、NDK、消息推送、二维码生成与扫描、分享和第三方登录、Bmob云服务、Afinal框架、 XUtils框架、版本控制、性能测试(听云)、App发布上线、Vitamio 跨平台播放器、EventBus、Android MVP 架构等。

    10602 人正在学习 去看看 郭宏志

Android RecyclerView 二级列表实现

2017.5.16 添加demo

Demo

git

简述

在开发 Android APP 的时候,难免会需要实现二级列表的情况,而在自己的项目中使用的列表是 android.support.v7.widget 包里面的 RecyclerView,好处是可以根据情况实现不同样式的列表,可扩展程度高。而坏处是什么都要自己实现。所以在想要用 RecyclerView 实现的二级列表的时候,却发现没有类似 ListViewExpandableListView,只能自己去实现。

实现基础

在使用 RecyclerView 的时候,与 ListView 类似,需要创建一个 Adapter 去告诉 RecyclerView 如何工作1,而在创建 RecyclerViewAdapter 的时候,一般需要重载以下几个方法:
onCreateViewHolder() 为每个项目创建 ViewHolder
onBindViewHolder() 处理每个 item
getItemViewType()onCreateViewHolder 前调用,返回 item 类型
getItemCount() 获取 item 总数
加载 RecyclerView 的过程如下图:

Created with Raphaël 2.1.0StartgetItemCount()getItemViewType()onCreateViewHolder()onBindViewHolder()End

除此之外,还需要创建一个 ViewHolder 用于寻找自定义 item的各个控件。

实现思路

根据上述,在实现二级列表的时候,我们在 onCreateViewHolder()onBindViewHolder() 中,判断是加载一级项目(GroupItem)还是二级子项目(SubItem)。

实现过程

二级列表数据格式

一般来说,一个 GroupItem 下面有一个,或多个 SubItem,一对多。
在这里,用一个 DataTree 来封装这种数据格式,代码如下:

public class DataTree<K, V> {

    private K groupItem;
    private List<V> subItems;

    public DataTree(K groupItem, List<V> subItems) {
        this.groupItem = groupItem;
        this.subItems = subItems;
    }

    public K getGroupItem() {
        return groupItem;
    }

    public List<V> getSubItems() {
        return subItems;
    }
}

RecyclerView Item状态

ItemStatus 用封装列表每一项的状态,包括:
viewType item的类型,group item 还是 subitem
groupItemIndex 一级索引位置
subItemIndex 如果该 item 是一个二级子项目,则保存子项目索引

    private static class ItemStatus {

        public static final int VIEW_TYPE_GROUPITEM = 0;
        public static final int VIEW_TYPE_SUBITEM = 1;

        private int viewType;
        private int groupItemIndex = 0;
        private int subItemIndex = -1;

        public ItemStatus() {
        }

        public int getViewType() {
            return viewType;
        }

        public void setViewType(int viewType) {
            this.viewType = viewType;
        }

        public int getGroupItemIndex() {
            return groupItemIndex;
        }

        public void setGroupItemIndex(int groupItemIndex) {
            this.groupItemIndex = groupItemIndex;
        }

        public int getSubItemIndex() {
            return subItemIndex;
        }

        public void setSubItemIndex(int subItemIndex) {
            this.subItemIndex = subItemIndex;
        }
    }

ViewHolder

这里的 groupItemsubItem 分别用不同的布局文件,所以我把 ViewHolder 分开写,如下:

    public static class GroupItemViewHolder extends RecyclerView.ViewHolder {
        ...
        public GroupItemViewHolder(View itemView) {
            super(itemView);
            ...
        }
    }

    public static class SubItemViewHolder extends RecyclerView.ViewHolder {
        ...
        public SubItemViewHolder(View itemView) {
            super(itemView);
            ...
        }
    }

其它属性和方法

context
list dataTrees 用于显示的数据
list<Boolean> groupItemStatus 保存 groupItem 状态,开还是关

    //向外暴露设置显示数据的方法
    public void setDataTrees(List<DataTree<Album, Track>> dt) {
        this.dataTrees = dt;
        initGroupItemStatus(groupItemStatus);
        notifyDataSetChanged();
    }

    //设置初始值,所有 groupItem 默认为关闭状态
    private void initGroupItemStatus(List l) {
        for (int i = 0; i < dataTrees.size(); i++) {
            l.add(false);
        }
    }

getItemStatusByPosition() 方法实现

顾名思义,用于根据 position 来计算判断该 item 的状态,返回一个 ItemStatus

position

代码如下:

private ItemStatus getItemStatusByPosition(int position) {

        ItemStatus itemStatus = new ItemStatus();

        int count = 0;    //计算groupItemIndex = i 时,position最大值
        int i = 0;

        //轮询 groupItem 的开关状态
        for (i = 0; i < groupItemStatus.size(); i++ ) {

            //pos刚好等于计数时,item为groupItem
            if (count == position) {
                itemStatus.setViewType(ItemStatus.VIEW_TYPE_GROUPITEM);
                itemStatus.setGroupItemIndex(i);
                break;

            //pos大于计数时,item为groupItem(i - 1)中的某个subItem
            } else if (count > position) {

                itemStatus.setViewType(ItemStatus.VIEW_TYPE_SUBITEM);
                itemStatus.setGroupItemIndex(i - 1);
                itemStatus.setSubItemIndex(position - ( count - dataTrees.get(i - 1).getSubItems().size() ) );
                break;

            }

            //无论groupItem状态是开或者关,它在列表中都会存在,所有count++
            count++;

            //当轮询到的groupItem的状态为“开”的话,count需要加上该groupItem下面的子项目数目
            if (groupItemStatus.get(i)) {

                count += dataTrees.get(i).getSubItems().size();

            }


        }

        //简单地处理当轮询到最后一项groupItem的时候
        if (i >= groupItemStatus.size()) {
            itemStatus.setGroupItemIndex(i - 1);
            itemStatus.setViewType(ItemStatus.VIEW_TYPE_SUBITEM);
            itemStatus.setSubItemIndex(position - ( count - dataTrees.get(i - 1).getSubItems().size() ) );
        }

        return itemStatus;
    }

getItemCount()方法实现

该方法在显示列表的时候会执行多次,如果返回的项目计数不正确的话程序会出现错误奔溃,代码如下:

    @Override
    public int getItemCount() {

        Logger.i("1");

        int itemCount = 0;

        if (groupItemStatus.size() == 0) {
            return 0;
        }

        for (int i = 0; i < dataTrees.size(); i++) {

            if (groupItemStatus.get(i)) {
                itemCount += dataTrees.get(i).getSubItems().size() + 1;
            } else {
                itemCount++;
            }

        }

        return itemCount;
    }

其它方法实现

  • getItemViewType()

该方法会在 onCreateViewHolder() 前执行,并返回 int viewType,代码如下:

    @Override
    public int getItemViewType(int position) {
        return getItemStatusByPosition(position).getViewType();
    }
  • onCreateViewHolder()
    根据不同的由 getItemViewType() 返回的 viewType 选择不同的项目布局,代码如下:
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v;
        RecyclerView.ViewHolder viewHolder = null;

        if (viewType == ItemStatus.VIEW_TYPE_GROUPITEM) {

            v = LayoutInflater.from(parent.getContext()).inflate(R.layout
                    .item_artist_detail_album, parent, false);
            viewHolder = new GroupItemViewHolder(v);

        } else if (viewType == ItemStatus.VIEW_TYPE_SUBITEM) {

            v = LayoutInflater.from(parent.getContext()).inflate(R.layout
                    .item_artist_detail_track, parent, false);
            viewHolder = new SubItemViewHolder(v);
        }

        return viewHolder;
    }
  • onBindViewHolder()
    根据不同的 viewType 绑定不同的 ViewHolder ,代码如下:
   @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        final ItemStatus itemStatus = getItemStatusByPosition(position);

        final DataTree<Album, Track> dt = dataTrees.get(itemStatus.getGroupItemIndex());

        if ( itemStatus.getViewType() == ItemStatus.VIEW_TYPE_GROUPITEM ) {

            final GroupItemViewHolder groupItemVh = (GroupItemViewHolder) holder;

            . . .    //加载groupItem,处理groupItem控件

            groupItemVh.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    int groupItemIndex = itemStatus.getGroupItemIndex();

                    if ( !groupItemStatus.get(groupItemIndex) ) {

                        . . .  //groupItem由“关闭”状态到“打开”状态

                        groupItemStatus.set(groupItemIndex, true);
                        notifyItemRangeInserted(groupItemVh.getAdapterPosition() + 1, dt.getSubItems().size());

                    } else {

                     . . .    //groupItem由“打开”状态到“关闭”状态

                    groupItemStatus.set(groupItemIndex, false);
                        notifyItemRangeRemoved(groupItemVh.getAdapterPosition() + 1, dt.getSubItems().size());

                    }

                }
            });

        } else if (itemStatus.getViewType() == ItemStatus.VIEW_TYPE_SUBITEM) {

            SubItemViewHolder subItemVh = (SubItemViewHolder) holder;

             . . .    //加载subItem,处理subItem控件

            subItemVh.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                 . . .    //点击subItem处理

                }
            });
        }
    }

总结

二级列表对 RecyclerView 小小地扩展,在实现的过程中,有点麻烦的地方是对特定的 item 进行识别,即 getItemViewType() 的实现,在这里,我简单地用遍历轮询的方法去判断,应该会有更简单更节省资源的方法。实现二级列表之后,理论上可以实现多级列表,可以试试。

在用这个方法实现之前,有尝试过有 View 提供的方法—— View.setTag() ,但是由于 RecyclerView 的加载机制,当列表被划出界面时,会被销毁,而重新划进来显示时,RecyclerView 会重新创建新的 item,而不是之前的那个,所以,之前的 Tag 会不见,最后没能实现出来,感兴趣的同学可以试试。


  1. [Android RecyclerView 使用完全解析 体验艺术般的控件 - hongyang - CSDN博客]http://blog.csdn.net/lmj623565791/article/details/45059587
2017-02-17 11:53:56 u010702071 阅读数 4531
  • Android 高级专题

    本课程包含23章,共计95个小节课程,内容包括:Android多线程、网络编程、数据解析、数据存储、多媒体、Android 图形图像、Android 动画、GPS 定位、 Android 传感器编程、蓝牙、NDK、消息推送、二维码生成与扫描、分享和第三方登录、Bmob云服务、Afinal框架、 XUtils框架、版本控制、性能测试(听云)、App发布上线、Vitamio 跨平台播放器、EventBus、Android MVP 架构等。

    10602 人正在学习 去看看 郭宏志

之前项目中产品需求带二级的评论列表,首先想到是QQ空间评论列表。
先上效果图
这里写图片描述
下面我们来分析一下布局结构,首先一级列表是listview,然后二级列表也可以有多条,为了省事我只添加了一条,第一反应是listview嵌套listview,然而listview嵌套又会出现显示不全等问题,于是自定义listview解决高度问题,废话不多说直接上代码:
布局文件最外层是竖直的LinearLayout

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <com.world.compet.view.CircleImageView
        android:id="@+id/commentItemImg"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:layout_marginLeft="12dp"
        android:layout_marginTop="15dp"
        android:contentDescription="@string/app_name"
        android:src="@drawable/photo_pic" />

    <RelativeLayout
        android:id="@+id/rl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="12dp"
        android:layout_marginTop="13dp" >

        <!-- 评论人昵称 -->

        <TextView
            android:id="@+id/commentNickname"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:text="游客1"
            android:textColor="#333333"
            android:textSize="14sp" />

        <ImageView
            android:id="@+id/male"
            android:layout_width="11dp"
            android:layout_height="11dp"
            android:layout_alignTop="@+id/commentNickname"
            android:layout_centerVertical="true"
            android:layout_marginLeft="7dp"
            android:layout_marginTop="4dp"
            android:visibility="invisible"
            android:layout_toRightOf="@+id/commentNickname"
            android:background="@drawable/nv" />
        <!-- 评论时间 -->

        <TextView
            android:id="@+id/commentItemTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_below="@id/commentNickname"
            android:layout_marginTop="3dp"
            android:text="6秒前"
            android:textColor="#b6b6b6"
            android:textSize="11sp" />
        <!-- 评论人内容 -->

        <LinearLayout
            android:id="@+id/description_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/commentItemTime"
            android:orientation="vertical"
            android:paddingTop="15dip" >

            <TextView
                android:id="@+id/commentItemContent"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_below="@id/commentItemTime"
                android:ellipsize="end"
                android:textColor="#666666"
                android:lineSpacingExtra="2dp"
                android:textSize="14sp" />


        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_comment"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_alignParentRight="true"
            android:layout_marginTop="2dp"
            android:orientation="horizontal" >

            <LinearLayout
                android:id="@+id/ll_dig"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="20dp"
                android:orientation="horizontal" >

                <ImageView
                    android:id="@+id/like"
                    android:layout_width="15dp"
                    android:layout_height="15dp"
                    android:layout_marginRight="4dp"
                    android:background="@drawable/pinglunzan1" />

                <TextView
                    android:id="@+id/like_num"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="0"
                    android:textColor="#b6b6b6"
                    android:textSize="12dp" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/ll_comm"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal" >

                <ImageView
                    android:id="@+id/com"
                    android:layout_width="15dp"
                    android:layout_height="15dp"
                    android:layout_marginRight="4dp"
                    android:background="@drawable/xiaoxiicon" />

                <TextView
                    android:id="@+id/tv_commentnum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="0"
                    android:textColor="#b6b6b6"
                    android:textSize="12dp" />
            </LinearLayout>
        </LinearLayout>

        <com.world.compet.view.NoScrollListView
            android:id="@+id/replyList"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/description_layout"
            android:layout_marginTop="15dp"
            android:divider="#00000000"
            android:focusable="false" />

        <View
            android:id="@+id/line"
            android:layout_width="match_parent"
            android:layout_height="15dp"
            android:layout_below="@+id/replyList"
            android:background="#00ffffff" />
    </RelativeLayout>
</LinearLayout>



<View
    android:id="@+id/nolast"
    android:layout_width="match_parent"
    android:layout_height="0.5dp"
    android:layout_marginLeft="57dp"
    android:layout_marginRight="12dp"
    android:background="#f3f3f3" />
<View
    android:id="@+id/last"
    android:visibility="gone"
    android:layout_width="match_parent"
    android:layout_height="0.5dp"
    android:layout_marginRight="12dp"
    android:background="#f3f3f3" />

自定义listview:
package com.example.jing.commentdemo.view;

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

public class NoScrollListView extends ListView {
public NoScrollListView(Context context, AttributeSet attrs) {
super(context,attrs);
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, mExpandSpec);
}

}
下面主要是adapter
public class CommentAdapter extends BaseAdapter {

private Context context;
private List<CommentBean> list;
private LayoutInflater inflater;
private replyClickListener rClickListener;
private AnimateFirstDisplayListener animateFirstDisplayListener = new AnimateFirstDisplayListener();
@SuppressWarnings("unused")
private String nid;
private Handler handler;
int maxDescripLine = 5;

// int isdigg=0;

public CommentAdapter(String nid, Context context,
                      List<CommentBean> list, int resourceId, Handler handler) {
    this.nid = nid;
    this.list = list;
    this.context = context;
    inflater = LayoutInflater.from(context);
    this.handler = handler;
}

@Override
public int getCount() {
    return list.size();
}

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

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

@SuppressLint("CutPasteId")
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    final CommentBean bean = list.get(position);
    ViewHolder holder = null;
    if (convertView == null) {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.all_comment_item, null);
        holder.nolast=convertView.findViewById(R.id.nolast);
        holder.last=convertView.findViewById(R.id.last);
        holder.commentItemImg = (CircleImageView) convertView
                .findViewById(R.id.commentItemImg);
        holder.commentNickname = (TextView) convertView
                .findViewById(R.id.commentNickname);
        holder.likeNum = (TextView) convertView.findViewById(R.id.like_num);
        holder.commentItemTime = (TextView) convertView
                .findViewById(R.id.commentItemTime);
        holder.commentItemContent = (TextView) convertView
                .findViewById(R.id.commentItemContent);
        holder.replyList = (NoScrollListView) convertView
                .findViewById(R.id.replyList);

        holder.ivLike = (ImageView) convertView.findViewById(R.id.like);
        holder.ivSex = (ImageView) convertView.findViewById(R.id.male);
        holder.replayNum = (TextView) convertView
                .findViewById(R.id.tv_commentnum);
        holder.digLayout = (LinearLayout) convertView
                .findViewById(R.id.ll_dig);
        holder.comLayout = (LinearLayout) convertView
                .findViewById(R.id.ll_comm);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    if (position==list.size()-1) {
        holder.last.setVisibility(View.VISIBLE);
        holder.nolast.setVisibility(View.GONE);
    }else {
        holder.nolast.setVisibility(View.VISIBLE);
        holder.last.setVisibility(View.GONE);

    }
    final ComReplyAdapter adapter = new ComReplyAdapter(
            context, bean.getL2_comment(), R.layout.reply_item);
     holder.replyList.setAdapter(adapter);
    // Utility.setListViewHeightBasedOnChildren(holder.replyList);
    holder.comLayout
            .setOnClickListener(new TextviewClickListener(position) {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    super.onClick(v);
                }
            });
    holder.digLayout
            .setOnClickListener(new TextviewClickListener(position) {
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    super.onClick(v);
                }

            });
    holder.commentItemContent.setOnClickListener(new TextviewClickListener(
            position) {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            super.onClick(v);
        }

    });
    holder.replayNum.setText(bean.getComment_count());
    if (holder.commentItemImg.getTag() == null
            || !holder.commentItemImg.getTag().toString()
                    .equals(bean.getAvatar())) {

        App.getImageLoader().displayImage(bean.getAvatar(),
                holder.commentItemImg, App.getInstance().getOptions(),
                animateFirstDisplayListener);
    }
    holder.commentItemImg.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            // 跳转个人主页
             Toast.makeText(context, bean.getNick_name(),
             Toast.LENGTH_SHORT).show();

        }
    });
    holder.commentNickname.setText(bean.getNick_name());
    holder.commentItemTime.setText(bean.getCreate_time() + " "
            + bean.getUnivs_name());
    // holder.commentItemContent.setText(bean.getContent());
    final TextView descriptionView = (TextView) convertView
            .findViewById(R.id.commentItemContent);
    descriptionView.setText(bean.getContent());




    holder.likeNum.setText(bean.getDigg_count());
    // notifyDataSetChanged();
    adapter.setOnCommentClickListenern(new ComReplyAdapter.commentClickListener() {

        @Override
        public void OnCommentClick(String realName, String tuid,
                                   String parentid, int sonPosition) {
            // TODO Auto-generated method stub
            // SKApp.getInstance().showErrToast(realName);
            rClickListener.onClick(realName, tuid, parentid, position,
                    sonPosition);

        }
    });
    if (bean.getL2_comment().size() > 0) {
        holder.replyList.setVisibility(View.VISIBLE);
    } else {
        holder.replyList.setVisibility(View.GONE);
    }
    return convertView;
}

private final class ViewHolder {
    public CircleImageView commentItemImg; // 评论人图片
    public TextView commentNickname; // 评论人昵称
    public TextView likeNum; // 点赞人数
    public TextView commentItemTime; // 评论时间
    public TextView commentItemContent; // 评论内容
    public NoScrollListView replyList; // 评论回复列表
    public ImageView ivLike;
    public ImageView ivSex;
    public TextView replayNum;
    public LinearLayout digLayout;
    public LinearLayout comLayout;
    public View last;
    public View nolast;
    // public Button moreButton;
    // public View line;

}

/**
 * 事件点击监听器
 */
private class TextviewClickListener implements OnClickListener {

    int position;

    public TextviewClickListener(int position) {
        this.position = position;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.ll_dig:
            Message digmsg = handler.obtainMessage();
            digmsg.what = 10;
            digmsg.arg1 = position;

            handler.sendMessage(digmsg);
            break;
        case R.id.ll_comm:
            Message msg = handler.obtainMessage();
            msg.what = 11;
            msg.arg1 = position;
            handler.sendMessage(msg);
            break;
        case R.id.commentItemContent:
            Message msg1 = handler.obtainMessage();
            msg1.what = 11;
            msg1.arg1 = position;
            handler.sendMessage(msg1);
            break;
        }
    }
}

public interface replyClickListener {
    public void onClick(String realName, String tuid, String parentid,
                        int pos, int sonPosition);
}

public void SetOnRepalClickListener(replyClickListener rListener) {

    rClickListener = rListener;

}

}
二级adapter
public class ComReplyAdapter extends BaseAdapter {

private List<L2CommentBean> list;
private LayoutInflater inflater;
private TextView replyContent;
private SpannableString ss;
private commentClickListener commClickListener;
private Context context;

public ComReplyAdapter(Context context,
                       List<L2CommentBean> list, int resourceId) {
    this.context = context;
    this.list = list;
    inflater = LayoutInflater.from(context);
}

@Override
public int getCount() {
    return list.size();
}

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

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

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    final L2CommentBean bean = list.get(position);
    convertView = inflater.inflate(R.layout.reply_item, null);
    replyContent = (TextView) convertView.findViewById(R.id.replyContent);

    final String replyNickName = bean.getNick_name() + " ";
    final String commentNickName = " " + bean.getTo_nick_name();
    String replyContentStr = bean.getContent();
    // 用来标识在 Span 范围内的文本前后输入新的字符时是否把它们也应用这个效果
    // Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括)
    // Spanned.SPAN_INCLUSIVE_EXCLUSIVE(前面包括,后面不包括)
    // Spanned.SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,后面包括)
    // Spanned.SPAN_INCLUSIVE_INCLUSIVE(前后都包括)
    if (!TextUtils.isEmpty(commentNickName)) {

        ss = new SpannableString(replyNickName + "回复" + commentNickName
                + " " + replyContentStr);
    } else {
        ss = new SpannableString(replyNickName + " " + replyContentStr);

    }

    ss.setSpan(new ForegroundColorSpan(Color.parseColor("#22bfa7")), 0,
            replyNickName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ss.setSpan(new ForegroundColorSpan(Color.parseColor("#22bfa7")),
            replyNickName.length() + 2, replyNickName.length()
                    + commentNickName.length() + 2,
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    // 为回复的人昵称添加点击事件----前面的名字
    ss.setSpan(new TextSpanClick(replyNickName) {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            super.onClick(v);

// Toast.makeText(context,”个人中心”,Toast.LENGTH_SHORT).show();
}
}, 0, replyNickName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// //为评论的人的添加点击事件——-后面的名字
ss.setSpan(new TextSpanClick(commentNickName) {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
super.onClick(v);
// Toast.makeText(context,”个人中心”,Toast.LENGTH_SHORT).show();
}
}, replyNickName.length() + 2,
replyNickName.length() + commentNickName.length() + 2,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
replyContent.setText(ss);

    // 添加点击事件时,必须设置
    replyContent.setMovementMethod(LinkMovementMethod.getInstance());
    replyContent.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            // Toast.makeText(context, replyNickName+"~~",
            // Toast.LENGTH_SHORT).show();


                commClickListener.OnCommentClick(replyNickName,
                        bean.getUid(), bean.getParent_comment_id(),
                        position);

        }
    });
    return convertView;
}

private class TextSpanClick extends ClickableSpan {
    @SuppressWarnings("unused")
    private String nam;

    public TextSpanClick(String name) {
        nam = name;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        ds.setUnderlineText(false);// 取消下划线
    }

    @Override
    public void onClick(View v) {
        // 跳转个人主页
        // Toast.makeText(context, nam, Toast.LENGTH_SHORT).show();
    }
}

public interface commentClickListener {
    public void OnCommentClick(String realName, String tuid,
                               String parentid, int sonPosition);
}

public void setOnCommentClickListenern(commentClickListener comListener) {
    // if (commClickListener==null) {

    commClickListener = comListener;
    // }
}

public void addAll(List<L2CommentBean> list) {
    this.list = list;
    notifyDataSetChanged();
}

}
activity中使用:

 mAdapter = new CommentAdapter("0", MainActivity.this,
                comments, R.layout.comment_item, handler);
        mAdapter.SetOnRepalClickListener(new CommentAdapter.replyClickListener() {
            @Override
            public void onClick(String realName, String tuid, String parentid,
                                int pos, int sonPosition) {// 二级评论的回复
                Toast.makeText(MainActivity.this, "二级的回复", Toast.LENGTH_SHORT).show();

            }
        });
        mListView.setAdapter(mAdapter);
private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 10:

                    break;
                case 11:// 一级评论的回复

                    break;
                default:
                    break;
            }

        }
    };

demo地址:http://download.csdn.net/detail/u010702071/9756595
如果不足之处还望指正,谢谢!

2016-03-30 21:46:25 qq_28766327 阅读数 9553
  • Android 高级专题

    本课程包含23章,共计95个小节课程,内容包括:Android多线程、网络编程、数据解析、数据存储、多媒体、Android 图形图像、Android 动画、GPS 定位、 Android 传感器编程、蓝牙、NDK、消息推送、二维码生成与扫描、分享和第三方登录、Bmob云服务、Afinal框架、 XUtils框架、版本控制、性能测试(听云)、App发布上线、Vitamio 跨平台播放器、EventBus、Android MVP 架构等。

    10602 人正在学习 去看看 郭宏志

因为工作的关系,需要做一个省市二级联动。
1、首先,实现这个功能所用到的控件是android 的spinner
2、要做一个省市二级联动,首先我们要有所有省及其主要城市的数据,这里我给一个我的百度云的链接。大家可以自行前去下载

这里写链接内容

3、下面是我对该资料,及省市二级联动实现的分析

二级联动思路整理

这个json数据太大了,不能每次都循环遍历所有数据

1首先要获得省的列表
在json数据中,所有fGuid的值都为0,可以根据这个得到所有的省的列表。可以只解析前34个json数据的值(省的信息排在该json的前面,34已经足够将所有的省的信息获取到),可以有效的减少程序运行
2将省的信息放入spinner中
3省被选择后要获得城市的信息
城市的fGuid的值都不为空,fGuid的值代表的是城市所属的省,他的值是省的Guid的值。所以,所有省的Guid值都必须被保存
这时判断json中的fGuid就可以得出所有该省城市的数据
同一个省的城市在该json数据中都是连续的。当找到一个属于该省的程序后,如果连续出现五个不属于该省的城市,查找停止。
4用户点击所选城市时,所需要的最终数据是cityNo其他都是不用的。所以,要抽取出来的数据就是cityName(用于spinner显示),cityNo 实际要用的数据
总结: 省需要获取的信息是省的cityName(用于spinner显示)、guid(用于查找该省下的城市)
城市需要获得的信息是cityName(用于spinner显示)、cityNo

4以下是我实现二级联动的代码

package com.zhiyinqing;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
 
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
 
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;
 
public class MainActivity extends Activity {
 
    HashMap<String, String> provinceHash = new HashMap<String, String>();
    String[] provinceString = new String[34];
 
    HashMap<String, String> cityHash = new HashMap<String, String>();
    String[] cityString;
 
    String file;
 
    String cityNo = null;// 最重要的参数,选中的城市的cityNo
 
    private ArrayAdapter<String> proviceAdapter;
    private ArrayAdapter<String> cityAdapter;
    Spinner provinceSpinner;
    Spinner citySpinner;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        provinceSpinner = (Spinner) findViewById(R.id.spinnerprovince);
        citySpinner = (Spinner) findViewById(R.id.spinnercity);
 
        file = readFile(); // 读取txt文件
        getProvinces(file); // 得到省的列表
 
        // 设置spinner,不用管什么作用
        proviceAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, provinceString);
        proviceAdapter
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);// 设置下拉风格
        provinceSpinner.setAdapter(proviceAdapter); // 将adapter 添加到spinner中
        provinceSpinner.setOnItemSelectedListener(new ProvinceSelectedListener(
                MainActivity.this));// 添加监听
        provinceSpinner.setVisibility(View.VISIBLE);// 设置默认值
 
    }
 
    public String readFile() {
 
        /*
         * 读取文件中数据的方法
         */
 
        InputStream myFile = null;
        myFile = getResources().openRawResource(R.raw.ub_city);
        BufferedReader br = null;
 
        try {
            br = new BufferedReader(new InputStreamReader(myFile, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Log.e("debug", e.toString());
        }
        String temp;
        String str = "";
        try {
            while ((temp = br.readLine()) != null) {
                str = str + temp;
                // Log.i("zhiyinqing", "断点3"+temp);
            }
            br.close();
            myFile.close();
            return str;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "error";
        }
    }
 
    public void getProvinces(String jsonData) {
 
        /*
         * 从json字符串中得到省的信息
         */
 
        JSONArray jsonArray = null;
        try {
            jsonArray = new JSONArray(jsonData);
            for (int i = 0; i < 34; i++) {
                // 获取了34个省市区信息
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String guid = jsonObject.getString("guid");
                String cityName = jsonObject.getString("cityName");
                // Log.i("zhiyinqing", i+guid+cityName);
                provinceHash.put(cityName, guid);
                provinceString[i] = cityName;
 
            }
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
    public String[] getCitys(String guid, String jsonData) {
        /*
         * 此方法用于查找一个省下的所有城市
         */
        // 初始化hashmap
        cityHash.clear();
        // 暂时存放城市的数组
        String[] cityBuffer = new String[21];
        int j = 0;
 
        // 解析数据
        JSONArray jsonArray;
        try {
            jsonArray = new JSONArray(jsonData);
            int length = jsonArray.length();
            int i = 33;
            int continuous = 0;// 这个变量用于判断是否连续几次没有找到,如果是,则该省信息全部找到了
            boolean isFind = false;
             
            while (i < length) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String fGuid = jsonObject.getString("fGuid");
                String cityName = jsonObject.getString("cityName");
                String cityNo = jsonObject.getString("cityNo");
                if (fGuid.equals(guid)) {
                    isFind = true;
                    cityHash.put(cityName, cityNo);
                    cityBuffer[j] = cityName;
                    j++;
                    // Log.i("zhiyinqing", cityName);
                } else {
                    if (isFind == true) {
                        continuous += 1;
 
                        if (continuous > 5) {
                            Log.i("zhiyinqing", "城市数:" + j);
                            break;
                        }
                    }
                }
                i++;
            }
             
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String[] citys = new String[j];
        for(int i=0;i<j;i++){
            citys[i] = cityBuffer[i];
        }
        return citys;
    }
 
    class ProvinceSelectedListener implements OnItemSelectedListener {
 
        Context context;
 
        // 省被选择的监听器
 
        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
 
            String provinceName = provinceString[arg2];
            Toast.makeText(context, provinceName, Toast.LENGTH_LONG).show();
            String guid = provinceHash.get(provinceName);
            cityString = getCitys(guid, file);
 
            // 省被选中后,初始化城市Spinner
            cityAdapter = new ArrayAdapter<String>(context,
                    android.R.layout.simple_spinner_item, cityString);
            cityAdapter
                    .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);// 设置下拉风格
            citySpinner.setAdapter(cityAdapter); // 将adapter 添加到spinner中
            citySpinner.setOnItemSelectedListener(new CitySelectedListener());// 添加监听
            citySpinner.setVisibility(View.VISIBLE);// 设置默认
 
        }
 
        @Override
        public void onNothingSelected(AdapterView<?> arg0) {
            // TODO Auto-generated method stub
 
        }
 
        public ProvinceSelectedListener(Context context) {
            this.context = context;
        }
 
    }
 
    class CitySelectedListener implements OnItemSelectedListener {
 
        // 城市被点击的监听事件
 
        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            String cityName = cityString[arg2];
            if (cityName.equals("") || cityName == null) {
                cityName = cityString[0];
                cityNo = cityHash.get(cityName);
 
            } else {
                cityNo = cityHash.get(cityName);
                Log.i("zhiyinqing", "cityNo" + cityNo);
            }
 
        }
 
        @Override
        public void onNothingSelected(AdapterView<?> arg0) {
            // TODO Auto-generated method stub
 
        }
 
    }
 
     
 
}

如果有帮到您,打个赏呗
在这里插入图片描述

Android二级列表

阅读数 484

没有更多推荐了,返回首页