实现如图效果(“下拉刷新”,“加载更多”用第三方组件自带的效果即可),其中图片使用Universal-Image-Loader设置内存缓存的最大值为20M,导入PullToRefresh库,并使用PullToRefreshScrollView组件实现下拉刷新、上拉加载更多。
1.封装网络请求工具类和网络状态判断工具类,应用打开时,判断网络是否可用,不可用时弹出对话框提示用户进入设置页面,网络正常时弹出吐司,提示网络正常。
2.使用ViewPage+Handler完成无限轮播效果,轮播图使用Universal-Image-Loader加载网上图片资源(图片链接自己准备),给轮播图里的图片设置点击事件,点击后打开“https://www.baidu.com”(轮播图使用第三方0分)
1.布局文件
<!--布局一:菜单布局、自动轮播-->
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.lianxi0112.MainActivity"> <android.support.design.widget.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="50dp" app:tabGravity="center" app:tabIndicatorColor="#fff" app:tabMode="scrollable" app:tabSelectedTextColor="#f89" app:tabTextColor="@color/colorPrimary"> </android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_below="@id/tab_layout" android:layout_marginTop="20dp" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> </RelativeLayout>
<!--布局二:条目-->
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"> <ImageView android:id="@+id/image_images" android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/ic_launcher"/> <TextView android:id="@+id/text_subhead" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_toRightOf="@id/image_images" android:text="【i5 MX150 2G显存】全高清窄边框"/> <TextView android:id="@+id/text_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_toRightOf="@id/image_images" android:layout_below="@id/text_subhead" android:textColor="#f00" android:text="¥ 5199.0"/> </RelativeLayout>
<!--布局三:上拉加载、下拉刷新、自动轮播、自定义Listview-->
<?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" android:background="#f89"> <com.handmark.pulltorefresh.library.PullToRefreshScrollView android:id="@+id/p_sv" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.ViewPager android:id="@+id/my_vp" android:layout_width="match_parent" android:layout_height="200dp"> </android.support.v4.view.ViewPager> <com.example.lianxi0112.MyListview android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent"> </com.example.lianxi0112.MyListview> </LinearLayout> </com.handmark.pulltorefresh.library.PullToRefreshScrollView> </LinearLayout>
<!--布局四:WedView-->
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.lianxi0112.Main2Activity" android:background="#ff0"> <WebView android:id="@+id/my_wv" android:layout_width="match_parent" android:layout_height="match_parent"></WebView> </RelativeLayout>
2.清单文件中进行配置
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.lianxi0112"> <!--权限配置--> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".Main2Activity"></activity> </application> </manifest>
3.MainActivity实现菜单栏和ViewPager轮播
package com.example.lianxi0112; import android.support.annotation.Nullable; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.ListView; import com.handmark.pulltorefresh.library.PullToRefreshScrollView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private PullToRefreshScrollView scrollView; private TabLayout tabLayout; private ViewPager viewPager; private ListView listView; private List<String> list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //找到资源控件的ID tabLayout=findViewById(R.id.tab_layout); viewPager = findViewById(R.id.view_pager); //创建集合 添加菜单数据 list = new ArrayList<>(); for (int i = 0; i <10 ; i++) { list.add("考试"+i); } //viewPager设置适配器 viewPager.setAdapter(new MyAdapter(getSupportFragmentManager())); //关联tabLayout与viewPager tabLayout.setupWithViewPager(viewPager); } //设置适配器 class MyAdapter extends FragmentPagerAdapter{ public MyAdapter(FragmentManager fm) { super(fm); } @Nullable @Override public CharSequence getPageTitle(int position) { return list.get(position); } @Override public Fragment getItem(int position) { MyFrangment myFrangment = new MyFrangment(); return myFrangment; } @Override public int getCount() { return list.size(); } } }
4.MyFragment实现图片自动轮播和上拉加载、下拉刷新
package com.example.lianxi0112; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.widget.ScrollView; import com.google.gson.Gson; import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.PullToRefreshScrollView; import java.util.ArrayList; import java.util.List; /** * Created by dell on 2018/1/12. */ public class MyFrangment extends Fragment{ private PullToRefreshScrollView scrollView; private ViewPager viewPager; private ListView listView; private List<String> list; private int index=1; //访问接口 private String url = "http://120.27.23.105/product/searchProducts?keywords=%E7%AC%94%E8%AE%B0%E6%9C%AC&source=android&page="+index; private List<RequestData.DataBean> data=new ArrayList<>(); private int type=1;//定义类型:1.刷新。2.加载 private MyAdapter myAdapter; //创建Handler实现无限轮播 private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); //获取当前页面显示的值 int item = viewPager.getCurrentItem(); item++; //将当前值赋给vp viewPager.setCurrentItem(item); //发送延迟消息 handler.sendEmptyMessageDelayed(0,1000); } }; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View v = inflater.inflate(R.layout.myfragment,container,false); //找到资源控件的ID scrollView = v.findViewById(R.id.p_sv); viewPager = v.findViewById(R.id.my_vp); listView = v.findViewById(R.id.list_view); //初始化scrollView数据 initpsv(); //轮播图实现 initlunbotu(); //网络请求 requestNetData(); return v; } private void requestNetData() { if(NetStateUtil.isConn(getActivity())){ MyTask myTask = new MyTask(new MyTask.Icallbacks() { @Override public void updateUiByjson(String jsonstr) { Gson gson = new Gson(); RequestData requestData = gson.fromJson(jsonstr, RequestData.class); //当类型等于1.将集合中数据删除 if(type==1){ data.clear(); } //加载时将数据全部添加其中 data.addAll(requestData.getData()); //设置适配器 setAdapter(); //关闭头尾布局 scrollView.onRefreshComplete(); } }); //请求url myTask.execute(url); } } private void setAdapter() { //判断适配器是否存在。不存在则创建 有则刷新 if(myAdapter==null){ myAdapter = new MyAdapter(getActivity(), data); listView.setAdapter(myAdapter); }else{ myAdapter.notifyDataSetChanged(); } } private void initlunbotu() { //设置图片路径 list = new ArrayList<>(); list.add("http://www.5068.com/uploads/allimg/160318/1-16031Q42P9.jpg"); list.add("http://i02.pic.sogou.com/c7e35f9ae6ce97c0"); list.add("http://i03.pic.sogou.com/28e54d7d26656db8"); list.add("http://i04.pic.sogou.com/ffc56cf9e2c6dbe4"); list.add("http://img.jrjimg.cn/2014/07/20140709070037199.jpg"); //设置适配器 viewPager.setAdapter(new MyvpAdapter(getActivity(),list)); //设置图片默认显示在中间 viewPager.setCurrentItem(list.size()*10000); //发送延迟消息 handler.sendEmptyMessageDelayed(0,1000); } private void initpsv() { scrollView.setMode(PullToRefreshBase.Mode.BOTH);//设置上拉加载、下拉刷新的功能 //设置监听监听 scrollView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ScrollView>() { @Override//下拉刷新 public void onPullDownToRefresh(PullToRefreshBase<ScrollView> pullToRefreshBase) { type=1; index=1; url = "http://120.27.23.105/product/searchProducts?keywords=%E7%AC%94%E8%AE%B0%E6%9C%AC&source=android&page="+index; requestNetData(); } @Override//上拉加载 public void onPullUpToRefresh(PullToRefreshBase<ScrollView> pullToRefreshBase) { type=2; index++; url = "http://120.27.23.105/product/searchProducts?keywords=%E7%AC%94%E8%AE%B0%E6%9C%AC&source=android&page="+index; requestNetData(); } }); } }
5.MyvpAdapter实现图片自动轮播的适配器
package com.example.lianxi0112; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.support.v4.app.FragmentActivity; import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer; import java.util.List; /** * Created by dell on 2018/1/12. */ class MyvpAdapter extends PagerAdapter{ private Context context; private List<String> list; private DisplayImageOptions options; public MyvpAdapter(Context context, List<String> list) { this.context=context; this.list=list; options = new DisplayImageOptions.Builder() .cacheInMemory(true)//使用内存缓存 .cacheOnDisk(true)//使用磁盘缓存 .showImageOnLoading(R.mipmap.ic_launcher)//设置正在下载的图片 .showImageForEmptyUri(R.mipmap.ic_launcher)//url为空或请求的资源不存在时 .showImageOnFail(R.mipmap.ic_launcher)//下载失败时显示的图片 .bitmapConfig(Bitmap.Config.RGB_565)//设置图片色彩模式 1px=2字节 .imageScaleType(ImageScaleType.EXACTLY)//设置图片的缩放模式 .displayer(new RoundedBitmapDisplayer(100))//设置圆角 30代表半径 自定义 .build(); } @Override public int getCount() { return Integer.MAX_VALUE;//设置图片为最大 } @Override public boolean isViewFromObject(View view, Object object) { return view==object; } @Override public Object instantiateItem(ViewGroup container, int position) { //创建显示图片的控件 ImageView imageView = new ImageView(context); //异步获取图片 ImageLoader.getInstance().displayImage(list.get(position%list.size()),imageView,options); //将控件加入容器 container.addView(imageView); //设置监听事件 进行点击图片加载WedView imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(context, Main2Activity.class); context.startActivity(intent); } }); //返回控件 return imageView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } }
5.MyAdapter实现条目的内容
package com.example.lianxi0112; import android.content.Context; import android.graphics.Bitmap; import android.support.v4.app.FragmentActivity; 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.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer; import java.util.List; /** * Created by dell on 2018/1/12. */ class MyAdapter extends BaseAdapter{ private Context context; private List<RequestData.DataBean> data; private DisplayImageOptions options; public MyAdapter(Context context, List<RequestData.DataBean> data) { this.context=context; this.data=data; options = new DisplayImageOptions.Builder() .cacheInMemory(true)//使用内存缓存 .cacheOnDisk(true)//使用磁盘缓存 .showImageOnLoading(R.mipmap.ic_launcher)//设置正在下载的图片 .showImageForEmptyUri(R.mipmap.ic_launcher)//url为空或请求的资源不存在时 .showImageOnFail(R.mipmap.ic_launcher)//下载失败时显示的图片 .bitmapConfig(Bitmap.Config.RGB_565)//设置图片色彩模式 1px=2字节 .imageScaleType(ImageScaleType.EXACTLY)//设置图片的缩放模式 .displayer(new RoundedBitmapDisplayer(100))//设置圆角 30代表半径 自定义 .build(); } @Override public int getCount() { return data.size(); } @Override public Object getItem(int i) { return data.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder holder; if(view==null){ view = View.inflate(context,R.layout.item,null); holder = new ViewHolder(); holder.images=view.findViewById(R.id.image_images); holder.subhead=view.findViewById(R.id.text_subhead); holder.price=view.findViewById(R.id.text_price); view.setTag(holder); }else{ holder = (ViewHolder) view.getTag(); } holder.subhead.setText(data.get(i).getSubhead()); holder.price.setText("¥"+data.get(i).getPrice()); ImageLoader.getInstance().displayImage(data.get(i).getImages(),holder.images,options); return view; } class ViewHolder{ ImageView images; TextView subhead; TextView price; } }
6.MyApplication异步获取图片的框架
package com.example.lianxi0112; import android.app.Application; import android.os.Environment; import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache; import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import java.io.File; /** * Created by dell on 2018/1/12. */ public class MyApplication extends Application{ @Override public void onCreate() { super.onCreate(); //自定义SD卡缓存目录 1.android默认cache-app被卸载时,缓存的目录一并被删除 2.自定义 File file = new File(Environment.getExternalStorageDirectory().getPath()+"/images"); //1.将Application初始化 进行全局配置 ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this) .memoryCacheExtraOptions(400,700)//缓存图片的最大的长和高 .threadPoolSize(3)//线程池的数量 .threadPriority(4)// .memoryCacheSize(20*1024*1024)//设置内存缓存区大小 .diskCacheSize(80*1024*1024)//设置SD卡缓存区大小 .diskCache(new UnlimitedDiscCache(file))//自定义SD卡缓存目录 .writeDebugLogs()//打印日志内容 .diskCacheFileNameGenerator(new Md5FileNameGenerator())//给缓存的文件名进行MD5加密处理 .build(); ImageLoader.getInstance().init(configuration); } }
7.MyTask网络请求、流转字符串
package com.example.lianxi0112; import android.os.AsyncTask; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * 使用AsyncTask+HttpURLConnection请求数据 * Created by e531 on 2017/10/12. */ public class MyTask extends AsyncTask<String,Void,String> { //申请一个接口类对象 private Icallbacks icallbacks; //将无参构造设置成私有的,使之在外部不能够调用 private MyTask(){} //定义有参构造方法 public MyTask(Icallbacks icallbacks) { this.icallbacks = icallbacks; } @Override protected String doInBackground(String... params) { String str=""; try { //使用HttpUrlConnection URL url=new URL(params[0]); HttpURLConnection connection=(HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setReadTimeout(5000); connection.setConnectTimeout(5000); if(connection.getResponseCode()==200){ InputStream inputStream=connection.getInputStream(); //调用工具类中的静态方法 str=StreamToString.streamToStr(inputStream,"utf-8"); } } catch (MalformedURLException e) { e.printStackTrace(); }catch (IOException e){ e.printStackTrace(); } return str; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); //解析,封装到bean,更新ui组件 icallbacks.updateUiByjson(s); } //定义一个接口 public interface Icallbacks{ /** * 根据回传的json字符串,解析并更新页面组件 * @param jsonstr */ void updateUiByjson(String jsonstr); } }
8.NetStateUtil:网络判断、有则请求、无则弹出对话框
package com.example.lianxi0112; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; public class NetStateUtil { /* * 判断网络连接是否已开 * true 已打开 false 未打开 * */ public static boolean isConn(Context context){ boolean bisConnFlag=false; ConnectivityManager conManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo network = conManager.getActiveNetworkInfo(); if(network!=null){ bisConnFlag=conManager.getActiveNetworkInfo().isAvailable(); } return bisConnFlag; } /** * 当判断当前手机没有网络时选择是否打开网络设置 * @param context */ public static void showNoNetWorkDlg(final Context context) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setIcon(R.mipmap.ic_launcher) // .setTitle(R.string.app_name) // .setMessage("当前无网络").setPositiveButton("设置", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 跳转到系统的网络设置界面 Intent intent = null; // 先判断当前系统版本 if(android.os.Build.VERSION.SDK_INT > 10){ // 3.0以上 intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS); }else{ intent = new Intent(); intent.setClassName("com.android.settings", "com.android.settings.WirelessSettings"); } context.startActivity(intent); } }).setNegativeButton("知道了", null).show(); } }9.StreamToString:流转字符串
package com.example.lianxi0112; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; public class StreamToString { public static String streamToStr(InputStream inputStream,String chartSet){ StringBuilder builder=new StringBuilder(); try { BufferedReader br=new BufferedReader(new InputStreamReader(inputStream,chartSet)); String con; while ((con=br.readLine())!=null){ builder.append(con); } br.close(); return builder.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } }
10.ListView自定义
package com.example.lianxi0112; import android.content.Context; import android.util.AttributeSet; import android.widget.ListView; /** * Created by dell on 2018/1/12. */ public class MyListview extends ListView{ public MyListview(Context context) { super(context); } public MyListview(Context context, AttributeSet attrs) { super(context, attrs); } public MyListview(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int spec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, spec); } }
11.跳转页面,加载WedView
package com.example.lianxi0112; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; public class Main2Activity extends AppCompatActivity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); //找到资源控件的ID webView = findViewById(R.id.my_wv); webView.loadUrl("http://news.baidu.com/"); webView.setWebChromeClient(new WebChromeClient()); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setJavaScriptCanOpenWindowsAutomatically(true); } }11.需解析的Json数据,创建一个类,Alt+S弹出窗口,将网络请求的数据复制在其中,直接保存即可