HorizontalScrollView Horizontal水平滑动栏和今日头条ViewPager的联动
来源:互联网 发布:s400防空导弹系统知乎 编辑:程序博客网 时间:2024/05/19 19:16
一. 传值的 MainActivity.java
package com.Horizaontal;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentPagerAdapter;import android.support.v4.view.ViewPager;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;public class MainActivity extends AppCompatActivity { private ViewPager viewPager; private MyIndicator myIndicator; private String[] titles; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewPager); myIndicator = (MyIndicator) findViewById(R.id.indicator); //1. 设置指示器标题 titles = new String[]{"头条","社会","国内","军事","娱乐","科技","时尚","财经","体育"}; myIndicator.setTitles(titles); viewPager.setOffscreenPageLimit(titles.length); //2. 为ViewPager设置适配器 viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public CharSequence getPageTitle(int position) { return titles[position]; } @Override public Fragment getItem(int position) { //获取标题,向Fragment传值 News_Fragment news_fragment = new News_Fragment(); Bundle bundle = new Bundle(); if (titles[position].equals("头条")){ bundle.putString("name","top"); }else if (titles[position].equals("社会")){ bundle.putString("name","shehui"); }else if (titles[position].equals("国内")){ bundle.putString("name","guonei"); }else if (titles[position].equals("军事")){ bundle.putString("name","junshi"); }else if (titles[position].equals("娱乐")){ bundle.putString("name","yule"); }else if (titles[position].equals("科技")){ bundle.putString("name","keji"); }else if (titles[position].equals("时尚")){ bundle.putString("name","shishang"); }else if (titles[position].equals("财经")){ bundle.putString("name","caijing"); }else if (titles[position].equals("体育")){ bundle.putString("name","tiyu"); } news_fragment.setArguments(bundle); return news_fragment; } @Override public int getCount() { return titles.length; } }); //3. 指示器要与ViewPager关联 myIndicator.setViewPager(viewPager); }}
二. 设置多条目展示的适配器
package com.Horizaontal;import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import com.nostra13.universalimageloader.core.ImageLoader;import java.util.List;import util.ImageLoaderUtil;public class NewsAdapter extends BaseAdapter{ private List<JsonBean.ResultBean.DataBean> list; private Context context; private int ONLY_TITLE = 0; private int IMAGE_ONE = 1; private int IMAGE_TWO = 2; private int IMAGE_THREE = 3; public NewsAdapter(Context context, List<JsonBean.ResultBean.DataBean> list) { this.context = context; this.list = list; } @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 int getViewTypeCount() { return 4; } @Override public int getItemViewType(int position) { /**每个fragment中展示新闻内容,要求:多条目加载和上拉加载,下拉刷新 多条目加载:奇数条目(第1357....)展示只有标题的布局 偶数条目(第2468.....)展示标题+图片样式的条目布局 */ if (position % 2 == 0){ if (list.get(position).getThumbnail_pic_s() != null && list.get(position).getThumbnail_pic_s02() != null &&list.get(position).getThumbnail_pic_s03() != null ){ return IMAGE_THREE; }else if (list.get(position).getThumbnail_pic_s() != null && list.get(position).getThumbnail_pic_s02() != null){ return IMAGE_TWO; } return IMAGE_ONE; } return ONLY_TITLE; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (getItemViewType(position) == IMAGE_ONE){ Image01_ViewHolder holder; if (convertView == null){ convertView =View.inflate(context, R.layout.item_layout01,null); holder =new Image01_ViewHolder(); //查找控件 holder.author_name = (TextView) convertView.findViewById(R.id.author_name); holder.title = (TextView) convertView.findViewById(R.id.title); holder.image = (ImageView) convertView.findViewById(R.id.image); convertView.setTag(holder); }else { holder = (Image01_ViewHolder) convertView.getTag(); } //获取数据重新赋值 holder.title.setText(list.get(position).getTitle()); holder.author_name.setText(list.get(position).getAuthor_name()); ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s(),holder.image, ImageLoaderUtil.getDefaultOption()); }else if (getItemViewType(position) == IMAGE_TWO){ Image02_ViewHolder holder; if (convertView == null){ convertView =View.inflate(context, R.layout.item_layout02,null); holder =new Image02_ViewHolder(); //查找控件 holder.image002 = (ImageView) convertView.findViewById(R.id.image002); holder.image001 = (ImageView) convertView.findViewById(R.id.image001); holder.title = (TextView) convertView.findViewById(R.id.title); convertView.setTag(holder); }else { holder = (Image02_ViewHolder) convertView.getTag(); } //获取数据重新赋值 holder.title.setText(list.get(position).getTitle()); ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s(),holder.image001,ImageLoaderUtil.getDefaultOption()); ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s02(),holder.image002,ImageLoaderUtil.getDefaultOption()); } else if (getItemViewType(position) == IMAGE_THREE){ Image03_ViewHolder holder; if (convertView == null){ convertView =View.inflate(context, R.layout.item_layout03,null); holder =new Image03_ViewHolder(); //查找控件 holder.image01 = (ImageView) convertView.findViewById(R.id.image01); holder.image02 = (ImageView) convertView.findViewById(R.id.image02); holder.image03 = (ImageView) convertView.findViewById(R.id.image03); holder.title = (TextView) convertView.findViewById(R.id.title); convertView.setTag(holder); }else { holder = (Image03_ViewHolder) convertView.getTag(); } //获取数据重新赋值 holder.title.setText(list.get(position).getTitle()); ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s(),holder.image01, ImageLoaderUtil.getDefaultOption()); ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s02(),holder.image02,ImageLoaderUtil.getDefaultOption()); ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s03(),holder.image03,ImageLoaderUtil.getDefaultOption()); }else { Only_Title_ViewHolder holder; if (convertView == null){ convertView =View.inflate(context, R.layout.title_layout,null); holder =new Only_Title_ViewHolder(); //查找控件 holder.title = (TextView) convertView.findViewById(R.id.title); convertView.setTag(holder); }else { holder = (Only_Title_ViewHolder) convertView.getTag(); } //获取数据重新赋值 holder.title.setText(list.get(position).getTitle()); } return convertView; } //自定义优化缓存类 static class Only_Title_ViewHolder{ TextView title; } static class Image01_ViewHolder{ TextView title,author_name; ImageView image; } static class Image02_ViewHolder{ TextView title; ImageView image001,image002; } static class Image03_ViewHolder{ TextView title; ImageView image01,image02,image03; }}
三. 自定义的指示器
package com.Horizaontal;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.util.TypedValue;import android.view.Gravity;import android.view.View;import android.widget.HorizontalScrollView;import android.widget.LinearLayout;import android.widget.TextView;public class MyIndicator extends HorizontalScrollView implements ViewPager.OnPageChangeListener{ private static final int COLOR_TEXT_NORMAL = 0xFF000000; private static final int COLOR_INDICATOR_COLOR = Color.BLACK; private Context context; private int tabWidth; private String[] titles; private int count; private Paint mPaint; private float mTranslationX; private ViewPager viewPager; private int SCREEN_WIDTH; private float lineheight = 2.0f; public MyIndicator(Context context) { this(context, null); } public MyIndicator(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public MyIndicator(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context){ this.context = context; mPaint = new Paint(); mPaint.setColor(COLOR_INDICATOR_COLOR); mPaint.setStrokeWidth(lineheight);//底部指示线的宽度 setHorizontalScrollBarEnabled(false); SCREEN_WIDTH = context.getResources().getDisplayMetrics().widthPixels; } public void setLineheight(float height){ this.lineheight = height; mPaint.setStrokeWidth(lineheight);//底部指示线的宽度 } public void setViewPager(ViewPager viewPager){ this.viewPager = viewPager; viewPager.addOnPageChangeListener(this); } public void setTitles(String[] titles){ this.titles = titles; count = titles.length; tabWidth = SCREEN_WIDTH/4; generateTitleView(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); tabWidth = SCREEN_WIDTH/4; } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); canvas.save(); canvas.translate(mTranslationX, getHeight() - lineheight); canvas.drawLine(0, 0, tabWidth, 0, mPaint);//(startX, startY, stopX, stopY, paint) canvas.restore(); } public void scroll(int position, float offset) { mTranslationX = tabWidth * (position + offset); scrollTo((int)mTranslationX-(SCREEN_WIDTH-tabWidth)/2, 0); invalidate(); } private void generateTitleView() { if (getChildCount() > 0) this.removeAllViews(); count = titles.length; LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); linearLayout.setLayoutParams(new LinearLayout.LayoutParams(count*tabWidth, LinearLayout.LayoutParams.MATCH_PARENT)); for (int i = 0; i < count; i++) { TextView tv = new TextView(getContext()); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(tabWidth, LinearLayout.LayoutParams.MATCH_PARENT); tv.setGravity(Gravity.CENTER); tv.setTextColor(COLOR_TEXT_NORMAL); tv.setText(titles[i]); tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);//字体大小 tv.setLayoutParams(lp); final int finalI = i; tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(viewPager!=null){ viewPager.setCurrentItem(finalI,false); } } }); linearLayout.addView(tv); } addView(linearLayout); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { scroll(position, positionOffset); } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { }}
四. 接收数据的Fragment
package com.Horizaontal;import android.os.AsyncTask;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.google.gson.Gson;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;import util.NetConnectionUtil;import util.StringUtil;import view.XListView;public class News_Fragment extends Fragment implements XListView.IXListViewListener{ private List<JsonBean.ResultBean.DataBean> list = new ArrayList<>(); private NewsAdapter adapter; private XListView xListView; private String data; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.news_layout, container, false); //查找控件 xListView = (XListView) view.findViewById(R.id.XListView); //设置XListView的上拉刷新功能 xListView.setPullLoadEnable(true); xListView.setPullRefreshEnable(true); //XListView的监听事件 xListView.setXListViewListener(this); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //获取传递的标题数据 Bundle bundle = getArguments(); data = bundle.getString("name", "top"); //判断网络状态,异步加载数据 if (NetConnectionUtil.isNetConnectioned(getActivity())){ getDataFromNet(data); }else{ NetConnectionUtil.setNetConnectionWork(getActivity()); } } private void getDataFromNet(final String data) { AsyncTask<Void,Void,String> task = new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { try { //路径 String path = "http://v.juhe.cn/toutiao/index?type="+data+"&key=c4479ad58f41e7f78a8fa073d0b1f1b5"; //连接网络 URL url = new URL(path); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setReadTimeout(5000); connection.setConnectTimeout(5000); //响应数据 int responseCode = connection.getResponseCode(); if (responseCode == 200){ InputStream inputStream = connection.getInputStream(); String json = StringUtil.streamToString(inputStream,"utf-8"); return json; } } catch (Exception e) { e.printStackTrace(); } return ""; } @Override protected void onPostExecute(String json) { if (json== null || json.isEmpty()){ }else { //解析数据 JsonBean jsonBean = new Gson().fromJson(json, JsonBean.class); if (jsonBean != null && jsonBean.getResult().getData() != null){ //把获取的数据添加到集合中 list.addAll(jsonBean.getResult().getData()); //设置适配器 setAdapter(); //停止刷新数据 xListView.stopRefresh(); //设置刷新的时间 Date date = new Date(System.currentTimeMillis()); SimpleDateFormat format = new SimpleDateFormat("HH:mm"); xListView.setRefreshTime(format.format(date)); } } } }; task.execute(); } //设置适配器的方法 private void setAdapter() { if (adapter == null){ adapter = new NewsAdapter(getActivity(), list); xListView.setAdapter(adapter); }else { adapter.notifyDataSetChanged(); } } @Override public void onRefresh() { //判断网络状态,异步加载数据 if (NetConnectionUtil.isNetConnectioned(getActivity())){ getDataFromNet(data); }else{ NetConnectionUtil.setNetConnectionWork(getActivity()); } } @Override public void onLoadMore() { //判断网络状态,异步加载数据 if (NetConnectionUtil.isNetConnectioned(getActivity())){ getDataFromNet(data); }else{ NetConnectionUtil.setNetConnectionWork(getActivity()); } }}
五. 自定义bean类
六. util工具类包:
1. 全局化配置ImageLoader类的 BaseApplication.java
package com.util;import android.app.Application;//全局初始化Application类public class BaseApplication extends Application { @Override public void onCreate() { super.onCreate(); //配置imageLoader ImageLoaderUtil.init(this); }}
2. 配置imageLoader的 ImageLoaderUtil.java
package com.util;import android.content.Context;import android.graphics.Bitmap;import com.month.R;import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;import com.nostra13.universalimageloader.core.DisplayImageOptions;import com.nostra13.universalimageloader.core.ImageLoader;import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;import com.nostra13.universalimageloader.core.assist.ImageScaleType;import com.nostra13.universalimageloader.core.assist.QueueProcessingType;import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;import com.nostra13.universalimageloader.core.download.BaseImageDownloader;import com.nostra13.universalimageloader.utils.StorageUtils;import java.io.File;public class ImageLoaderUtil { /** * 初始化imageLoader * @param context */ public static void init(Context context) { //1.获取配置config对象 File cacheDir = StorageUtils.getCacheDirectory(context); //缓存文件夹路径 ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context) .threadPoolSize(3) // default 线程池内加载的数量 .threadPriority(Thread.NORM_PRIORITY - 2) // default 设置当前线程的优先级 .tasksProcessingOrder(QueueProcessingType.FIFO) // default .denyCacheImageMultipleSizesInMemory() .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //可以通过自己的内存缓存实现 .memoryCacheSize(2 * 1024 * 1024) // 内存缓存的最大值 .memoryCacheSizePercentage(13) // default .diskCache(new UnlimitedDiscCache(cacheDir)) // default 可以自定义缓存路径 .diskCacheSize(50 * 1024 * 1024) // 50 Mb sd卡(本地)缓存的最大值 .diskCacheFileCount(100) // 可以缓存的文件数量 // default为使用HASHCODE对UIL进行加密命名, 还可以用MD5(new Md5FileNameGenerator())加密 .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) .imageDownloader(new BaseImageDownloader(context)) // default .imageDecoder(new BaseImageDecoder(true)) // default .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default .writeDebugLogs() // 打印debug log .build(); //开始构建 //2.初始化配置...ImageLoader.getInstance()图片加载器的对象,单例模式 ImageLoader.getInstance().init(config); } /** * imageLoader加载图片的默认选项 * @return */ public static DisplayImageOptions getDefaultOption(){ DisplayImageOptions options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.app) // 设置图片下载期间显示的默认图片 .showImageForEmptyUri(R.drawable.app) // 设置图片Uri为空或是错误的时候显示的图片 .showImageOnFail(R.drawable.app) // 设置图片加载或解码过程中发生错误显示的图片 .resetViewBeforeLoading(true) // default 设置图片在加载前是否重置、复位 .delayBeforeLoading(1000) // 下载前的延迟时间 .cacheInMemory(true) // default 设置下载的图片是否缓存在内存中 .cacheOnDisk(true) // default 设置下载的图片是否缓存在SD卡中 .considerExifParams(true) // default .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 设置图片以如何的编码方式显示 .bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型 .displayer(new SimpleBitmapDisplayer()) // default 还可以设置圆角图片new RoundedBitmapDisplayer(20) .build(); return options; } /** * imageLoader加载圆角图片....指定圆角的大小 * @return */ public static DisplayImageOptions getRoundedOption(int corner){ DisplayImageOptions options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.app) // 设置图片下载期间显示的图片 .showImageForEmptyUri(R.drawable.app) // 设置图片Uri为空或是错误的时候显示的图片 .showImageOnFail(R.drawable.app) // 设置图片加载或解码过程中发生错误显示的图片 .resetViewBeforeLoading(true) // default 设置图片在加载前是否重置、复位 .delayBeforeLoading(1000) // 下载前的延迟时间 .cacheInMemory(true) // default 设置下载的图片是否缓存在内存中 .cacheOnDisk(true) // default 设置下载的图片是否缓存在SD卡中 .considerExifParams(true) // default .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 设置图片以如何的编码方式显示 .bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型 .displayer(new RoundedBitmapDisplayer(corner)) // default 还可以设置圆角图片new RoundedBitmapDisplayer(20) .build(); return options; }}
3. 判断网络连接的工具类 NetConnectionUtil.java
package com.util;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.net.ConnectivityManager;import android.net.NetworkInfo;import android.provider.Settings;/** * 判断网络连接的工具类 */public class NetConnectionUtil { /** * 判断是否有网络连接的方法 */ public static boolean isNetConnectioned(Context context){ //1. 获取网络连接对象 ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); //2. 获取NetworkInfo对象,获取网络连接的信息 NetworkInfo info = manager.getActiveNetworkInfo(); //3. 信息不为空时,就代表网络可用 if (info != null){ return info.isAvailable(); } return false; } /** * 网络无连接时跳转页面,弹出对话框进行网络的设置 */ public static void setNetConnectionWork(final Context context){ AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("网络加载错误!"); builder.setMessage("网络连接不可用,是否设置网络?"); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //跳转到系统的设置网络的界面 Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); context.startActivity(intent); } }); builder.setNegativeButton("取消",null); builder.show(); }}
4. 解析json数据的 StringUtil.java
package com.util;
import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;public class StringUtil { public static String streamToString(InputStream inputStream, String charset) { try { InputStreamReader inputStreamReader = new InputStreamReader(inputStream,charset); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String s = null; StringBuilder builder = new StringBuilder(); while ((s = bufferedReader.readLine()) != null){ builder.append(s); } bufferedReader.close(); return builder.toString(); } catch (Exception e) { e.printStackTrace(); } return null; }}
七. view 包下的 XListView实现类:
1. XListView.java
/** * @file XListView.java * @package me.maxwin.view * @create Mar 18, 2012 6:28:41 PM * @author Maxwin * @description An ListView support (a) Pull down to refresh, (b) Pull up to load more. * Implement IXListViewListener, and see stopRefresh() / stopLoadMore(). */package view;import androidthree_1509d.MyViewpager.R;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewTreeObserver.OnGlobalLayoutListener;import android.view.animation.DecelerateInterpolator;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ListAdapter;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.Scroller;import android.widget.TextView;public class XListView extends ListView implements OnScrollListener { private float mLastY = -1; // save event y private Scroller mScroller; // used for scroll back private OnScrollListener mScrollListener; // user's scroll listener // the interface to trigger refresh and load more. private IXListViewListener mListViewListener; // -- header view private XListViewHeader mHeaderView; // header view content, use it to calculate the Header's height. And hide it // when disable pull refresh. private RelativeLayout mHeaderViewContent; private TextView mHeaderTimeView; private int mHeaderViewHeight; // header view's height private boolean mEnablePullRefresh = true; private boolean mPullRefreshing = false; // is refreashing. // -- footer view private XListViewFooter mFooterView; private boolean mEnablePullLoad; private boolean mPullLoading; private boolean mIsFooterReady = false; // total list items, used to detect is at the bottom of listview. private int mTotalItemCount; // for mScroller, scroll back from header or footer. private int mScrollBack; private final static int SCROLLBACK_HEADER = 0; private final static int SCROLLBACK_FOOTER = 1; private final static int SCROLL_DURATION = 400; // scroll back duration private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px // at bottom, trigger // load more. private final static float OFFSET_RADIO = 1.8f; // support iOS like pull // feature. /** * @param context */ public XListView(Context context) { super(context); initWithContext(context); } public XListView(Context context, AttributeSet attrs) { super(context, attrs); initWithContext(context); } public XListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initWithContext(context); } private void initWithContext(Context context) { mScroller = new Scroller(context, new DecelerateInterpolator()); // XListView need the scroll event, and it will dispatch the event to // user's listener (as a proxy). super.setOnScrollListener(this); // init header view mHeaderView = new XListViewHeader(context); mHeaderViewContent = (RelativeLayout) mHeaderView .findViewById(R.id.xlistview_header_content); mHeaderTimeView = (TextView) mHeaderView .findViewById(R.id.xlistview_header_time); addHeaderView(mHeaderView); // init footer view mFooterView = new XListViewFooter(context); // init header height mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mHeaderViewHeight = mHeaderViewContent.getHeight(); getViewTreeObserver() .removeGlobalOnLayoutListener(this); } }); } @Override public void setAdapter(ListAdapter adapter) { // make sure XListViewFooter is the last footer view, and only add once. if (mIsFooterReady == false) { mIsFooterReady = true; addFooterView(mFooterView); } super.setAdapter(adapter); } /** * enable or disable pull down refresh feature. * * @param enable */ public void setPullRefreshEnable(boolean enable) { mEnablePullRefresh = enable; if (!mEnablePullRefresh) { // disable, hide the content mHeaderViewContent.setVisibility(View.INVISIBLE); } else { mHeaderViewContent.setVisibility(View.VISIBLE); } } /** * enable or disable pull up load more feature. * * @param enable */ public void setPullLoadEnable(boolean enable) { mEnablePullLoad = enable; if (!mEnablePullLoad) { mFooterView.hide(); mFooterView.setOnClickListener(null); //make sure "pull up" don't show a line in bottom when listview with one page setFooterDividersEnabled(false); } else { mPullLoading = false; mFooterView.show(); mFooterView.setState(XListViewFooter.STATE_NORMAL); //make sure "pull up" don't show a line in bottom when listview with one page setFooterDividersEnabled(true); // both "pull up" and "click" will invoke load more. mFooterView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startLoadMore(); } }); } } /** * stop refresh, reset header view. */ public void stopRefresh() { if (mPullRefreshing == true) { mPullRefreshing = false; resetHeaderHeight(); } } /** * stop load more, reset footer view. */ public void stopLoadMore() { if (mPullLoading == true) { mPullLoading = false; mFooterView.setState(XListViewFooter.STATE_NORMAL); } } /** * set last refresh time * * @param time */ public void setRefreshTime(String time) { mHeaderTimeView.setText(time); } private void invokeOnScrolling() { if (mScrollListener instanceof OnXScrollListener) { OnXScrollListener l = (OnXScrollListener) mScrollListener; l.onXScrolling(this); } } private void updateHeaderHeight(float delta) { mHeaderView.setVisiableHeight((int) delta + mHeaderView.getVisiableHeight()); if (mEnablePullRefresh && !mPullRefreshing) { // 未处于刷新状态,更新箭头 if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) { mHeaderView.setState(XListViewHeader.STATE_READY); } else { mHeaderView.setState(XListViewHeader.STATE_NORMAL); } } setSelection(0); // scroll to top each time } /** * reset header view's height. */ private void resetHeaderHeight() { int height = mHeaderView.getVisiableHeight(); if (height == 0) // not visible. return; // refreshing and header isn't shown fully. do nothing. if (mPullRefreshing && height <= mHeaderViewHeight) { return; } int finalHeight = 0; // default: scroll back to dismiss header. // is refreshing, just scroll back to show all the header. if (mPullRefreshing && height > mHeaderViewHeight) { finalHeight = mHeaderViewHeight; } mScrollBack = SCROLLBACK_HEADER; mScroller.startScroll(0, height, 0, finalHeight - height, SCROLL_DURATION); // trigger computeScroll invalidate(); } private void updateFooterHeight(float delta) { int height = mFooterView.getBottomMargin() + (int) delta; if (mEnablePullLoad && !mPullLoading) { if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load // more. mFooterView.setState(XListViewFooter.STATE_READY); } else { mFooterView.setState(XListViewFooter.STATE_NORMAL); } } mFooterView.setBottomMargin(height);// setSelection(mTotalItemCount - 1); // scroll to bottom } private void resetFooterHeight() { int bottomMargin = mFooterView.getBottomMargin(); if (bottomMargin > 0) { mScrollBack = SCROLLBACK_FOOTER; mScroller.startScroll(0, bottomMargin, 0, -bottomMargin, SCROLL_DURATION); invalidate(); } } private void startLoadMore() { mPullLoading = true; mFooterView.setState(XListViewFooter.STATE_LOADING); if (mListViewListener != null) { mListViewListener.onLoadMore(); } } @Override public boolean onTouchEvent(MotionEvent ev) { if (mLastY == -1) { mLastY = ev.getRawY(); } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mLastY = ev.getRawY(); break; case MotionEvent.ACTION_MOVE: final float deltaY = ev.getRawY() - mLastY; mLastY = ev.getRawY(); if (getFirstVisiblePosition() == 0 && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) { // the first item is showing, header has shown or pull down. updateHeaderHeight(deltaY / OFFSET_RADIO); invokeOnScrolling(); } else if (getLastVisiblePosition() == mTotalItemCount - 1 && (mFooterView.getBottomMargin() > 0 || deltaY < 0)) { // last item, already pulled up or want to pull up. updateFooterHeight(-deltaY / OFFSET_RADIO); } break; default: mLastY = -1; // reset if (getFirstVisiblePosition() == 0) { // invoke refresh if (mEnablePullRefresh && mHeaderView.getVisiableHeight() > mHeaderViewHeight) { mPullRefreshing = true; mHeaderView.setState(XListViewHeader.STATE_REFRESHING); if (mListViewListener != null) { mListViewListener.onRefresh(); } } resetHeaderHeight(); } else if (getLastVisiblePosition() == mTotalItemCount - 1) { // invoke load more. if (mEnablePullLoad && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA && !mPullLoading) { startLoadMore(); } resetFooterHeight(); } break; } return super.onTouchEvent(ev); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { if (mScrollBack == SCROLLBACK_HEADER) { mHeaderView.setVisiableHeight(mScroller.getCurrY()); } else { mFooterView.setBottomMargin(mScroller.getCurrY()); } postInvalidate(); invokeOnScrolling(); } super.computeScroll(); } @Override public void setOnScrollListener(OnScrollListener l) { mScrollListener = l; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (mScrollListener != null) { mScrollListener.onScrollStateChanged(view, scrollState); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // send to user's listener mTotalItemCount = totalItemCount; if (mScrollListener != null) { mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } } public void setXListViewListener(IXListViewListener l) { mListViewListener = l; } /** * you can listen ListView.OnScrollListener or this one. it will invoke * onXScrolling when header/footer scroll back. */ public interface OnXScrollListener extends OnScrollListener { public void onXScrolling(View view); } /** * implements this interface to get refresh/load more event. */ public interface IXListViewListener { public void onRefresh(); public void onLoadMore(); }}
2. XlistViewHeader.java
/** * @file XListViewHeader.java * @create Apr 18, 2012 5:22:27 PM * @author Maxwin * @description XListView's header */package view;import androidthree_1509d.MyViewpager.R;import android.content.Context;import android.util.AttributeSet;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.view.animation.Animation;import android.view.animation.RotateAnimation;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.ProgressBar;import android.widget.TextView;public class XListViewHeader extends LinearLayout { private LinearLayout mContainer; private ImageView mArrowImageView; private ProgressBar mProgressBar; private TextView mHintTextView; private int mState = STATE_NORMAL; private Animation mRotateUpAnim; private Animation mRotateDownAnim; private final int ROTATE_ANIM_DURATION = 180; public final static int STATE_NORMAL = 0; public final static int STATE_READY = 1; public final static int STATE_REFRESHING = 2; public XListViewHeader(Context context) { super(context); initView(context); } /** * @param context * @param attrs */ public XListViewHeader(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } private void initView(Context context) { // 初始情况,设置下拉刷新view高度为0 LayoutParams lp = new LayoutParams( LayoutParams.FILL_PARENT, 0); mContainer = (LinearLayout) LayoutInflater.from(context).inflate( R.layout.xlistview_header, null); addView(mContainer, lp); setGravity(Gravity.BOTTOM); mArrowImageView = (ImageView)findViewById(R.id.xlistview_header_arrow); mHintTextView = (TextView)findViewById(R.id.xlistview_header_hint_textview); mProgressBar = (ProgressBar)findViewById(R.id.xlistview_header_progressbar); mRotateUpAnim = new RotateAnimation(0.0f, -180.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION); mRotateUpAnim.setFillAfter(true); mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION); mRotateDownAnim.setFillAfter(true); } public void setState(int state) { if (state == mState) return ; if (state == STATE_REFRESHING) { // 显示进度 mArrowImageView.clearAnimation(); mArrowImageView.setVisibility(View.INVISIBLE); mProgressBar.setVisibility(View.VISIBLE); } else { // 显示箭头图片 mArrowImageView.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.INVISIBLE); } switch(state){ case STATE_NORMAL: if (mState == STATE_READY) { mArrowImageView.startAnimation(mRotateDownAnim); } if (mState == STATE_REFRESHING) { mArrowImageView.clearAnimation(); } mHintTextView.setText(R.string.xlistview_header_hint_normal); break; case STATE_READY: if (mState != STATE_READY) { mArrowImageView.clearAnimation(); mArrowImageView.startAnimation(mRotateUpAnim); mHintTextView.setText(R.string.xlistview_header_hint_ready); } break; case STATE_REFRESHING: mHintTextView.setText(R.string.xlistview_header_hint_loading); break; default: } mState = state; } public void setVisiableHeight(int height) { if (height < 0) height = 0; LayoutParams lp = (LayoutParams) mContainer .getLayoutParams(); lp.height = height; mContainer.setLayoutParams(lp); } public int getVisiableHeight() { return mContainer.getLayoutParams().height; }}
3. XListViewFooter.java
/** * @file XFooterView.java * @create Mar 31, 2012 9:33:43 PM * @author Maxwin * @description XListView's footer */package view;import androidthree_1509d.MyViewpager.R;import android.content.Context;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;public class XListViewFooter extends LinearLayout { public final static int STATE_NORMAL = 0; public final static int STATE_READY = 1; public final static int STATE_LOADING = 2; private Context mContext; private View mContentView; private View mProgressBar; private TextView mHintView; public XListViewFooter(Context context) { super(context); initView(context); } public XListViewFooter(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public void setState(int state) { mHintView.setVisibility(View.INVISIBLE); mProgressBar.setVisibility(View.INVISIBLE); mHintView.setVisibility(View.INVISIBLE); if (state == STATE_READY) { mHintView.setVisibility(View.VISIBLE); mHintView.setText(R.string.xlistview_footer_hint_ready); } else if (state == STATE_LOADING) { mProgressBar.setVisibility(View.VISIBLE); } else { mHintView.setVisibility(View.VISIBLE); mHintView.setText(R.string.xlistview_footer_hint_normal); } } public void setBottomMargin(int height) { if (height < 0) return ; LayoutParams lp = (LayoutParams)mContentView.getLayoutParams(); lp.bottomMargin = height; mContentView.setLayoutParams(lp); } public int getBottomMargin() { LayoutParams lp = (LayoutParams)mContentView.getLayoutParams(); return lp.bottomMargin; } /** * normal status */ public void normal() { mHintView.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.GONE); } /** * loading status */ public void loading() { mHintView.setVisibility(View.GONE); mProgressBar.setVisibility(View.VISIBLE); } /** * hide footer when disable pull load more */ public void hide() { LayoutParams lp = (LayoutParams)mContentView.getLayoutParams(); lp.height = 0; mContentView.setLayoutParams(lp); } /** * show footer */ public void show() { LayoutParams lp = (LayoutParams)mContentView.getLayoutParams(); lp.height = LayoutParams.WRAP_CONTENT; mContentView.setLayoutParams(lp); } private void initView(Context context) { mContext = context; LinearLayout moreView = (LinearLayout)LayoutInflater.from(mContext).inflate(R.layout.xlistview_footer, null); addView(moreView); moreView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); mContentView = moreView.findViewById(R.id.xlistview_footer_content); mProgressBar = moreView.findViewById(R.id.xlistview_footer_progressbar); mHintView = (TextView)moreView.findViewById(R.id.xlistview_footer_hint_textview); } }
1. activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <com.Horizaontal.MyIndicator android:background="@android:color/holo_blue_bright" android:layout_width="match_parent" android:layout_height="50dp" android:id="@+id/indicator"></com.Horizaontal.MyIndicator> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
2. 显示fragment的news_layout.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <view.XListView android:scrollbars="none" android:id="@+id/XListView" android:layout_width="match_parent" android:layout_height="match_parent"></view.XListView></LinearLayout>
3. 多条目展示数据的4种布局
(1)item_layout01.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_weight="2" android:layout_width="0dp" android:orientation="vertical" android:layout_height="wrap_content" android:layout_alignParentLeft="true"> <TextView android:textSize="18sp" android:id="@+id/title" android:textStyle="bold" android:layout_marginLeft="10dp" android:layout_marginTop="18dp" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:textSize="13sp" android:id="@+id/author_name" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <ImageView android:id="@+id/image" android:layout_weight="1" android:layout_width="0dp" android:layout_height="100dp" android:layout_marginRight="5dp" android:layout_gravity="center_vertical" /></LinearLayout>
(2)item_layout02.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:textSize="18sp" android:id="@+id/title" android:textStyle="bold" android:layout_marginLeft="10dp" android:layout_marginTop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:orientation="horizontal" android:layout_marginTop="18dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:layout_weight="1" android:layout_width="0dp" android:id="@+id/image001" android:layout_height="120dp" /> <ImageView android:layout_weight="1" android:layout_width="0dp" android:id="@+id/image002" android:layout_height="120dp" android:layout_marginLeft="3dp"/> <ImageView android:layout_weight="1" android:layout_width="0dp" android:layout_height="120dp" android:layout_marginLeft="3dp"/> </LinearLayout></LinearLayout>
(3)item_layout03.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:textSize="18sp" android:id="@+id/title" android:textStyle="bold" android:layout_marginLeft="10dp" android:layout_marginTop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:orientation="horizontal" android:layout_marginTop="18dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:layout_weight="1" android:id="@+id/image01" android:layout_width="0dp" android:layout_height="120dp" /> <ImageView android:layout_weight="1" android:id="@+id/image02" android:layout_width="0dp" android:layout_height="120dp" android:layout_marginLeft="3dp"/> <ImageView android:layout_weight="1" android:id="@+id/image03" android:layout_width="0dp" android:layout_height="120dp" android:layout_marginLeft="3dp"/> </LinearLayout></LinearLayout>
(4)title_layout.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/title" android:textSize="18sp" android:layout_height="60dp" android:gravity="center_vertical" android:layout_marginLeft="10dp" android:layout_width="wrap_content" /></LinearLayout>
4. 展示xlistview布局的2个xml
(1)xlistview_header.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="bottom" > <RelativeLayout android:id="@+id/xlistview_header_content" android:layout_width="fill_parent" android:layout_height="60dp" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:orientation="vertical" android:id="@+id/xlistview_header_text"> <TextView android:id="@+id/xlistview_header_hint_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/xlistview_header_hint_normal" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/xlistview_header_last_time" android:textSize="12sp" /> <TextView android:id="@+id/xlistview_header_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12sp" /> </LinearLayout> </LinearLayout> <ImageView android:id="@+id/xlistview_header_arrow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@id/xlistview_header_text" android:layout_centerVertical="true" android:layout_marginLeft="-35dp" android:src="@drawable/xlistview_arrow" /> <ProgressBar android:id="@+id/xlistview_header_progressbar" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignLeft="@id/xlistview_header_text" android:layout_centerVertical="true" android:layout_marginLeft="-40dp" android:visibility="invisible" /> </RelativeLayout></LinearLayout>
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" > <RelativeLayout android:id="@+id/xlistview_footer_content" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" > <ProgressBar android:id="@+id/xlistview_footer_progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:visibility="invisible" /> <TextView android:id="@+id/xlistview_footer_hint_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="@string/xlistview_footer_hint_normal" /> </RelativeLayout></LinearLayout>
5. values文件夹下的布局文件strings.xml添加以下代码:
<string name="xlistview_header_hint_normal">下拉刷新</string><string name="xlistview_header_hint_ready">松开刷新数据</string><string name="xlistview_header_hint_loading">正在加载...</string><string name="xlistview_header_last_time">上次更新时间:</string><string name="xlistview_footer_hint_normal">查看更多</string><string name="xlistview_footer_hint_ready">松开载入更多</string>
十. AndroidManifest.xml中
1. 加入请求网络数据 ,判断网络状态的权限;
2.声明imageloader的name属性。
阅读全文
0 0
- HorizontalScrollView Horizontal水平滑动栏和今日头条ViewPager的联动
- 类似今日头条网易新闻导航栏水平滑动的效果
- Android Android HorizontalScrollView滚动实现仿今日头条滑动
- 横向滑动菜单Tablayout和viewpager小圆点结合滑动仿今日头条
- 解决 HorizontalScrollView 和 ViewPager 的滑动冲突
- android仿今日头条之字体颜色随ViewPager的滑动步伐而改变
- Android开发——垂直水平滑动条scrollView和HorizontalScrollView的嵌套使用
- HorizontalScrollView和ViewPager联动效果
- 今日头条条目联动
- HorizontalScrollView 使用 实现textview和viewpager的联动
- TabLayout和ViewPager实现今日头条效果
- Viewpager实现今日头条顶部导航的功能
- ListView+Fragment+ViewPager配合,实现今日头条的效果
- 水平滚动和ViewPager联动
- 导航栏联动效果( HorizontalScrollView+ViewPager)
- HorizontalScrollView与ViewPager联动
- HorizontalScrollView作为导航栏和HorizontalScrollView的滑动
- 仿今日头条滑动评论效果
- php无限级分类实现评论及回复
- 面向对象设计原则—高内聚、低耦合。多聚合、少继承
- 实现select标签不通过ctrl实现多选,通过点击实现多选
- 数据结构实验一线性表的基本操作实现及其应用
- jn项目-解决前台中文参数传到后台乱码问题
- HorizontalScrollView Horizontal水平滑动栏和今日头条ViewPager的联动
- GAN and CGAN on MNIST dataset
- 300. Longest Increasing Subsequence
- 跨域Ajax访问的parsererror错误解决
- IMOOC java入门第三季——简易扑克牌游戏
- 笔记 -- 01 -- 技术文章网址
- 2011.03版本的arm gcc交叉编译器的bug
- iOS 11 上传应用 缺少图标报错
- sublime 的安装系列之 注册码与安装 Package Control------tex3