节目单左右滑动不好用,怎么办

先从动画开始看起

参考资料:

1. Android Animations - Tutorial

http://www.vogella.com/articles/AndroidAnimation/article.html

2. Is there any useful Android Animation Tutorial for beginners?

http://stackoverflow.com/questions/12229901/is-there-any-useful-android-animation-tutorial-for-beginners

3. Android Fragments and animation

http://stackoverflow.com/questions/4817900/android-fragments-and-animation


通过ListView实现一个二级树

在频道列表的需要中有频道类别和频道两种数据。频道是频道类别的下级数据。每个频道类别可以保含多个频道。在界面上频道类别和频道用两种布局来表现。频道类别只有名称和箭头,频道类别展开时,箭头向下,频道类别收起来时,箭头向右。频道中的数据项比较多比如名称、图标、状态等。


新建TvChannelAdapter继承BaseAdapter。在构造方法中定义两个参数context表示上下文,categorys表示数据,然后将在界面上可见的频道类别和频道两类数据取出来保存在itemList中。itemList表示adapter中的数据。

先看TvChannelAdapter中几个比较简单点的方法

private Context context;
private List<ChannelGroupData> categorys;
private List<Object> itemList;
private String selectChannelId = "000";
public TvChannelAdapter(Context context, List<ChannelGroupData> categorys) {
    this.context = context;
    this.categorys = categorys;
    this.initializeItemList();
}
private void initializeItemList() {
    itemList = new ArrayList<Object>();
    for (int i = 0; i < categorys.size(); i++) {
        ChannelGroupData category = categorys.get(i);
        itemList.add(category);
        if (category.isInExpanding())
            itemList.addAll(category.getData());
    }
}
@Override
public void notifyDataSetChanged() {
    if (itemList != null) {
        itemList.clear();
        itemList = null;
    }
    initializeItemList();
    super.notifyDataSetChanged();
}
@Override
public int getCount() {
    return itemList.size();
}
@Override
public Object getItem(int position) {
    return itemList.get(position);
}
@Override
public long getItemId(int position) {
    return position;
}

再来看TvChannelAdapter中很关键的方法getView。由于listView中要表现两种类型的数据,所以在getView方法中就要构造出两种类型的view。其中频道类别view用item_tvchannel_category.xml来构建,频道view用item_tvchannel_child.xml来构建。getView方法中返回的每个view的都来自itemList中的数据,view和数据用position关联对应。

public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder = new ViewHolder();
    if (itemList.get(position) instanceof ChannelItemData) {
        convertView = LayoutInflater.from(context).inflate(R.layout.item_tvchannel_child, null);
        initializeItemViewHolder(viewHolder, (ChannelItemData) itemList.get(position), convertView);
    } else {
        convertView = LayoutInflater.from(context).inflate(R.layout.item_tvchannel_category, null);
        initializeCategoryViewHolder(viewHolder, position, convertView);
    }
    return convertView;
}

在getView方法中有个Viewholder。它的定义如下,包含convertView中所有用到的view项。

private static class ViewHolder {
    AsyncImageView channelIcon;
    TextView channelName;
    TextView channelStatus;
    TextView categoryName;
    ImageView btnExpand;
}

当数据类型是频道类别时,调用initxxx来构建频道类别view中的内容。

频道类别点击时可以展开或者收起下级的频道。

private void initializeCategoryViewHolder(final ViewHolder viewHolder, final int position, View convertView) {
    final ChannelGroupData category = (ChannelGroupData) itemList.get(position);
    viewHolder.categoryName = (TextView) convertView.findViewById(R.id.channelGroupTitleName);
    viewHolder.btnExpand = (ImageView) convertView.findViewById(R.id.btnExpand);
    viewHolder.categoryName.setText(category.getName());
    viewHolder.btnExpand.setImageResource(category.isInExpanding() ? R.drawable.channel_expand_btn
            : R.drawable.channel_shrink_btn);
    viewHolder.btnExpand.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            if(category.isInExpanding()) {
                category.setInExpanding(false);
            } else {
                category.setInExpanding(true);
                shrinkOtherGroupTitle(position);
            }
            notifyDataSetChanged();
        }
    });
    convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            viewHolder.btnExpand.performClick();
        }
    });
}
public void shrinkOtherGroupTitle(int position) {
    for (int i = 0; i < itemList.size(); i++) {
        if (itemList.get(i) instanceof ChannelGroupData) {
            ((ChannelGroupData) itemList.get(i)).setInExpanding(i == position);
        }
    }
}

当数据类型表现为频道时,频道view也有个点击事件,点击时记下频道的id,然后调用notifyDataSetChanged方法,将点击的那个频道设置背景颜色表示选中状态。

private void initializeItemViewHolder(ViewHolder viewHolder, final ChannelItemData item, View convertView) {
    String hint = context.getResources().getString(R.string.live_play);
    String liveName = item.getLiveEpg().getName();
    if (TextUtils.isEmpty(liveName) || liveName.equalsIgnoreCase("null"))
        liveName = "(未知)";
    viewHolder.channelIcon = (AsyncImageView) convertView.findViewById(R.id.channelIcon);
    viewHolder.channelName = (TextView) convertView.findViewById(R.id.channelName);
    viewHolder.channelStatus = (TextView) convertView.findViewById(R.id.channelStatus);
    viewHolder.channelIcon.setCleartrue);
     viewHolder.channelIcon.setUrl(item.getIcon());
    viewHolder.channelName.setText(item.getName());
    viewHolder.channelStatus.setVisibility(View.VISIBLE);
    viewHolder.channelStatus.setText(hint + liveName);
                               
    if(selectChannelId.equals(item.getChannelId()))
        convertView.setBackgroundColor(context.getResources().getColor(R.color.lightblue));
    else
        convertView.setBackgroundColor(context.getResources().getColor(R.color.default_backgroud_color));
                               
    convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(item.getCategoryId() != null) {
                selectChannelId = item.getChannelId();
                notifyDataSetChanged();
            }
        }
    });
}