仿 淘寶頭條熱點 天貓頭條熱點 京東頭條熱點的自定義view 實現

最近整理了一下在自己負責的項目中用到的一些自定義View 實現一些比較熱門的功能,寫到這裏給自己留一份筆記,同時給那些有需要的朋友!

Demo主要是重寫了一下Linearlayout,對其填充你想要填充的佈局,由於在代碼中都添加了註釋,這裏不再做一一解釋了

先看看效果圖:

自定義View:

package com.example.nostalgia.myapplication.view;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView;

import com.example.nostalgia.myapplication.R;
import com.example.nostalgia.myapplication.Utils.DensityUtils;
import com.example.nostalgia.myapplication.bean.NewsInfo;

import java.util.List;

/**
 * Created by Nostalgia on 2016/12/8.
 * Title : 頭條熱點
 */
public class HomeScrollTopView extends LinearLayout {

    private Scroller mScroller;  //滾動實例
    private int size = 0;

    private List<NewsInfo> list;  //存放數據集合
    private final int DURING_TIME = 3000;  //滾動延遲
    private OnAdapterClickListener<NewsInfo> click;
    Context context;

    public HomeScrollTopView(Context context) {
        super(context);
        this.context = context;
        init();
    }

    public HomeScrollTopView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    private void init() {
        mScroller = new Scroller(getContext());
    }

    /**
     * 設置數據
     *
     * @param list
     */
    public void setData(List<NewsInfo> list) {
        this.list = list;
        if (list != null) {
            removeAllViews();
            size = list.size();
            for (int i = 0; i < size; i++) {
                addContentView(i);
            }
            if (list.size() > 1) {
                getLayoutParams().height = DensityUtils.dip2px(context, 40);//調節滾動數據的高度
                // 滾動
                cancelAuto();
                mHandler.sendEmptyMessageDelayed(0, DURING_TIME);
                smoothScrollBy(0, DensityUtils.dip2px(context, 40));
            }
        }
    }

    /**
     * 設置列表點擊事件
     *
     * @param click
     */
    public void setClickListener(OnAdapterClickListener<NewsInfo> click) {
        this.click = click;
    }

    /**
     * 重置數據
     */
    private void resetView() {
        NewsInfo homeBuyHouseGuide = list.get(0);
        list.remove(0);
        list.add(homeBuyHouseGuide);

        for (int i = 0; i < size; i++) {
            addContentView(i);
        }
    }

    /**
     * 取消滾動
     */
    public void cancelAuto() {
        mHandler.removeMessages(0);
    }

    private void addContentView(final int position) {
        ViewHolder mHolder;
        if (position >= getChildCount()) {
            mHolder = new ViewHolder();
            View v = View.inflate(getContext(), R.layout.home_scrolltopview, null);
            mHolder.biaoqianTv = (TextView) v.findViewById(R.id.tv_biaoqian);
            mHolder.nameTv = (TextView) v.findViewById(R.id.tv);
            v.setTag(mHolder);
            addView(v, LayoutParams.MATCH_PARENT, DensityUtils.dip2px(context, 40));
        } else {
            mHolder = (ViewHolder) getChildAt(position).getTag();
        }
        final NewsInfo newsInfo = list.get(position);
        if (!DensityUtils.isNullOrEmpty(newsInfo.tagname)) {
            mHolder.biaoqianTv.setText(newsInfo.tagname);
        } else {
            mHolder.biaoqianTv.setVisibility(GONE);
        }
        if (!DensityUtils.isNullOrEmpty(newsInfo.title)) {
            mHolder.nameTv.setText(newsInfo.title);
        } else {
            mHolder.nameTv.setVisibility(GONE);
        }
        mHolder.nameTv.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                if (click != null) {
                    click.onAdapterClick(null, newsInfo);
                }
            }
        });
    }

    private class ViewHolder {
        TextView nameTv;
        TextView biaoqianTv;
    }

    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            mHandler.removeMessages(0);
            mHandler.sendEmptyMessageDelayed(0, DURING_TIME);
            smoothScrollBy(0, DensityUtils.dip2px(context, 40));
            resetView();
        }

        ;
    };

    // 調用此方法設置滾動的相對偏移
    public void smoothScrollBy(int dx, int dy) {
        // 設置mScroller的滾動偏移量
        mScroller.startScroll(mScroller.getFinalX(), 0, dx, dy, DURING_TIME);
        invalidate();// 這裏必須調用invalidate()才能保證computeScroll()會被調用,否則不一定會刷新界面,看不到滾動效果
    }

    @Override
    public void computeScroll() {

        // 先判斷mScroller滾動是否完成
        if (mScroller.computeScrollOffset()) {

            // 這裏調用View的scrollTo()完成實際的滾動
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            // 必須調用該方法,否則不一定能看到滾動效果
            postInvalidate();

        }
        super.computeScroll();
    }

    public interface OnAdapterClickListener<T> {
        public void onAdapterClick(View v, T t);
    }
}
實體類:

package com.example.nostalgia.myapplication.bean;

import java.io.Serializable;

/**
 *         Created by
 *          Nostalgia
 *        on 2016/12/8.
 *
 *       Title: 實體類
 */
public class NewsInfo implements Serializable {
    private static final long serialVersionUID = 1L;

    public String type;// 類型 根據type值做跳轉使用

    public String tagname;// 標籤

    public String title;// 顯示標題

    public String news_url;//跳轉wap的信息url

    public NewsInfo(String type,String tagname,String title,String news_url) {
        super();
        this.type = type ;
        this.tagname = tagname ;
        this.title = title ;
        this.news_url = news_url ;
    }
}

調用主類:

package com.example.nostalgia.myapplication;


import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.example.nostalgia.myapplication.bean.NewsInfo;
import com.example.nostalgia.myapplication.view.HomeScrollTopView;

import java.util.ArrayList;

/**
 * Created by Nostalgia on 2016/12/8.
 * Title : 輪播頭條樣例
 */
public class MainActivity extends Activity {
    HomeScrollTopView topView;
    LinearLayout ll_homescrolltopview;
    private ArrayList<NewsInfo> newsInfoList = new ArrayList<>();

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

    private void initView() {
        topView = (HomeScrollTopView) findViewById(R.id.homescrolltopview);
        ll_homescrolltopview = (LinearLayout) findViewById(R.id.ll_homescrolltopview);
        ll_homescrolltopview.setVisibility(View.GONE);
    }

    private void initData() {
        if (newsInfoList.size() > 0) {
            newsInfoList.clear();
        }
        for (int i = 0; i < 6; i++) {
            newsInfoList.add(new NewsInfo("" + i, "標籤" + i, "這裏是測試標題" + i, ""));
        }
        /**
         * 上面改成接口返回的數據填充到list中
         */
        if (newsInfoList.size() < 1) {
            ll_homescrolltopview.setVisibility(View.GONE);
        } else {
            ll_homescrolltopview.setVisibility(View.VISIBLE);
            topView.setData(newsInfoList);
        }
    }

    private void initOper() {
        topView.setClickListener(new HomeScrollTopView.OnAdapterClickListener<NewsInfo>() {
            @Override
            public void onAdapterClick(View v, NewsInfo newsInfo) {
                if ("1".equals(newsInfo.type)) {
                    Toast.makeText(MainActivity.this, "標籤:" + newsInfo.tagname +"\n標題:" + newsInfo.title, Toast.LENGTH_SHORT).show();
                } else if ("2".equals(newsInfo.type)) {
                    Toast.makeText(MainActivity.this, "標籤:" + newsInfo.tagname + "\n標題:" + newsInfo.title, Toast.LENGTH_SHORT).show();
                } else if ("3".equals(newsInfo.type)) {
                    Toast.makeText(MainActivity.this, "標籤:" + newsInfo.tagname + "\n標題:" + newsInfo.title, Toast.LENGTH_SHORT).show();
                } else if ("4".equals(newsInfo.type)) {
                    Toast.makeText(MainActivity.this, "標籤:" + newsInfo.tagname + "\n標題:" + newsInfo.title, Toast.LENGTH_SHORT).show();
                } else if ("5".equals(newsInfo.type)) {
                    Toast.makeText(MainActivity.this, "標籤:" + newsInfo.tagname + "\n標題:" + newsInfo.title, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "標籤:" + newsInfo.tagname + "\n標題:" + newsInfo.title, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }


}
工具方法:

  /**
     * dp轉px
     *
     * @param context
     * @param
     * @return
     */
    public static int dip2px(Context context, float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, context.getResources().getDisplayMetrics());
    }


    /**
     * 判斷是否爲空
     *
     * @param text
     * @return
     */
    public static boolean isNullOrEmpty(String text) {
        if (text == null || "".equals(text.trim()) || text.trim().length() == 0
                || "null".equals(text.trim())) {
            return true;
        } else {
            return false;
        }
    }

Demo代碼已完整上傳到CSDN:點這裏去下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章