2016-08-16 16:40:31 qq_34908107 阅读数 1361
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21619 人正在学习 去看看 李忠义
Android之水滴落下的下拉刷新
非常逼真的水滴落下的下拉刷新。你可以配合ListView一起使用。
项目library下载地址:源码下载地址
我的demo下载地址(包含异步):水滴落下下拉刷新demo
效果图:































主要是用到一个库:WaveSwipeRefreshLayout
<span style="font-size:18px;">   <jp.co.recruit_lifestyle.android.widget.WaveSwipeRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/main_swipe"
        android:layout_below="@+id/toolbar"
        >

      <ListView
          android:id="@+id/main_list"
          android:layout_width="match_parent"
          android:layout_height="match_parent"


          />

    </jp.co.recruit_lifestyle.android.widget.WaveSwipeRefreshLayout></span>



MainActivuty:
<span style="font-size:18px;">package jp.co.recruit_lifestyle.sample;

import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

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

import jp.co.recruit_lifestyle.android.widget.WaveSwipeRefreshLayout;

public class MainActivity extends AppCompatActivity implements WaveSwipeRefreshLayout.OnRefreshListener {
  private Myadapter myadapter;
  private String str;
  private ListView mListview;


  private WaveSwipeRefreshLayout mWaveSwipeRefreshLayout;
  private LinkedList<String> list=new LinkedList<String>();



  @Override
  protected void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    initView();
    setSampleData();
  }

  private void initView() {
    mWaveSwipeRefreshLayout = (WaveSwipeRefreshLayout) findViewById(R.id.main_swipe);
    mWaveSwipeRefreshLayout.setColorSchemeColors(Color.WHITE, Color.WHITE);
    mWaveSwipeRefreshLayout.setOnRefreshListener(this);
    mWaveSwipeRefreshLayout.setWaveColor(Color.DKGRAY);
    //mWaveSwipeRefreshLayout.setMaxDropHeight(1300);

    mListview = (ListView) findViewById(R.id.main_list);
  }

  private void setSampleData() {

    for (int i = 0; i < 60; i++) {
      list.add("你好" );
    }
   myadapter=new Myadapter(list);
    mListview.setAdapter(myadapter);
  }
  class Myadapter extends BaseAdapter{
     List<String> list=new ArrayList<String>();
       public Myadapter (List<String> list){
      this.list=list;
    }

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

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

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

    @Override
    public View getView(int i, View converView, ViewGroup viewGroup) {
    View view;
      if (converView==null){
        view=View.inflate(MainActivity.this,R.layout.item,null);
      }else {
        view=converView;
      }
      TextView tvitem= (TextView) view.findViewById(R.id.tvitem);
      tvitem.setText(list.get(i));
      return view;
    }
  }

  private void refresh(){
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        // 更新が終了したらインジケータ非表示
        new Task().execute();

        mWaveSwipeRefreshLayout.setRefreshing(false);
      }
    }, 3000);
  }

  class Task extends AsyncTask<Void, Void,String>{

    @Override
    protected String doInBackground(Void... voids) {

      try {
        Thread.sleep(500);
        for (int a=0;a<10;a++){
 str="我是被添加的";

        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      return str;

    }

    @Override
    protected void onPostExecute(String stringlist) {
 list.addFirst(stringlist);
      myadapter.notifyDataSetChanged();



      mWaveSwipeRefreshLayout.setRefreshing(false);

      super.onPostExecute(stringlist);
    }
  }

  @Override
  protected void onResume() {
    mWaveSwipeRefreshLayout.setRefreshing(true);
    refresh();
    super.onResume();
  }

  @Override
  public void onRefresh() {
    refresh();
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
      mWaveSwipeRefreshLayout.setRefreshing(true);
      refresh();
      return true;
    }

    return super.onOptionsItemSelected(item);
  }
}
</span>


2013-12-27 09:08:05 siyehua 阅读数 960
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21619 人正在学习 去看看 李忠义

隐藏和显示异步任务,主要是通过控制内边距Pandding来实现

package com.siyehuazhilian.pushdownrefresh;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.siyehuazhilian.utils.DownImageTask;

public class MainActivity extends Activity {
	private RelativeLayout relativeLayout;
	private LinearLayout linearLayout;
	private ImageView imageView;

	private int refreshHeight;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		relativeLayout = (RelativeLayout) findViewById(R.id.relativelayout);
		linearLayout = (LinearLayout) findViewById(R.id.linearlayout_refresh);
		imageView = (ImageView) findViewById(R.id.imageview);

		ViewTreeObserver observer = linearLayout.getViewTreeObserver();
		observer.addOnPreDrawListener(new OnPreDrawListener() {

			@Override
			public boolean onPreDraw() {
				if (refreshHeight == 0) {
					refreshHeight = linearLayout.getMeasuredHeight();
					relativeLayout.setPadding(0, -refreshHeight, 0, 0);
				}
				return true;
			}
		});
	}

	private int startY;
	private int distance;

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			startY = (int) event.getRawY();
			break;
		case MotionEvent.ACTION_MOVE:
			distance = (int) ((event.getRawY() - startY) / 1.5);
			if (distance < linearLayout.getHeight() && distance > 0) {
				// distance = refreshHeight;
				relativeLayout.setPadding(0, linearLayout.getHeight()
						- distance, 0, 0);
			}
			break;
		case MotionEvent.ACTION_UP:
			// 手指离开,判断是满足刷新的要求
			// 要求distance要大于等于linearLayout.getHeight()的一半,
			// 如果大于,就让刷新界面完全展示出来并开启下载任务,如果小于,就重新隐藏刷新界面
			if (distance > linearLayout.getHeight() / 2) {
				relativeLayout.setPadding(0, 0, 0, 0);
				DownImageTask downImageTask = new DownImageTask(handler);
				downImageTask
						.execute("http://a.hiphotos.baidu.com/image/w%3D2048/sign=487f5fb067380cd7e61ea5ed957cad34/a6efce1b9d16fdfa575066eeb68f8c5494ee7bf6.jpg");
			} else {
				relativeLayout.setPadding(0, -linearLayout.getHeight(), 0, 0);
			}

			break;

		default:
			break;
		}
		return super.onTouchEvent(event);
	}

	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case 1:
				Bitmap bitmap = (Bitmap) msg.obj;
				imageView.setImageBitmap(bitmap);
				Toast.makeText(MainActivity.this, "更新完毕", 1000).show();
				// 下载完成还是要隐藏刷新的界面的
				relativeLayout.setPadding(0, -linearLayout.getHeight(), 0, 0);
				break;
			default:
				break;
			}
		};
	};

}

异步任务

package com.siyehuazhilian.utils;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;

public class DownImageTask extends AsyncTask<String, Integer, Bitmap> {
	private Handler handler;

	public DownImageTask(Handler handler) {
		this.handler = handler;
	}

	@Override
	protected Bitmap doInBackground(String... parems) {
		Bitmap bitmap = null;
		try {
			URL url = new URL(parems[0]);
			HttpURLConnection connection = (HttpURLConnection) url
					.openConnection();
			InputStream inputStream = connection.getInputStream();
			bitmap = BitmapFactory.decodeStream(inputStream);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return bitmap;
	}

	@Override
	protected void onPostExecute(Bitmap result) {
		super.onPostExecute(result);
		Message message = handler.obtainMessage(1, result);
		message.sendToTarget();
	}

}


2015-02-05 18:43:33 Programming2012 阅读数 666
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21619 人正在学习 去看看 李忠义

今日研究下拉刷新功能的实现,看过很多博客,尤其是这一篇可能大家看的多一些

参考的链接:http://blog.csdn.net/guolin_blog/article/details/9255575

我个人看了一两天还是没看懂,最后慢慢研究才终于看懂了。才发现,对于一个新手而言,首先需要的不是实现如何实现那么多复杂功能,什么回弹效果,异步加载等等。对新手更重要的是,首先学会怎么添加下拉头,实现下拉ListView时会出现下拉头,这才是对于新手来说想要首先解决的问题。

废话少说,开始正题。今天我要介绍的下拉刷新,效果如下图


在学这个之前,对于ListView和Adapter需要有一个基础的认识

下面是代码,有注释,我就不另外解释了

下拉头布局文件,很简单,就是一个LinearLayout和TextView

header.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="wrap_content"
    android:orientation="horizontal" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:text="下拉头"
        android:textSize="20sp"
        android:gravity="center"
        android:textColor="#ffffff"
        android:background="#aa0000"/>

</LinearLayout>


下拉头功能实现,继承了ListView

CustomView.java

package com.example.ddddddddddd;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;

public class CustomView extends ListView{

	int startY,y;//手指按下时的起始位置,以及滑动时的当前位置	
	int mHeadView_height;//下拉头高度
	int moveY;//手指滑动的距离
	LinearLayout mHeadView;//下拉头的布局
	
	//重写构造方法,这里必须有AttributeSet参数,看不懂也没事,反正这里用不到
	//如果重写的是CustomView(Context context)方法,运行时会报错Source not found
	public CustomView(Context context,AttributeSet attr){
		super(context,attr);
		
		LayoutInflater inflater=LayoutInflater.from(context);
		//填充下拉头
		mHeadView=(LinearLayout)inflater.inflate(R.layout.header, null);
		measureView(mHeadView);//测量下拉头的高度(单位是px)

		mHeadView_height=mHeadView.getMeasuredHeight();
		mHeadView.setPadding(0,-1*mHeadView_height,0, 0);
		addHeaderView(mHeadView, null, false);//添加下拉头
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch(event.getAction())
		{
			case MotionEvent.ACTION_DOWN:
				startY=(int) event.getY();
				break;
			case MotionEvent.ACTION_MOVE:
				y=(int) event.getY();
				moveY=y-startY;
				//为了使下拉时有拉力的感觉,所以下拉头位置变动量为MoveY的1/2
				mHeadView.setPadding(0,-1*mHeadView_height+moveY/2,0, 0);
				break;
			case MotionEvent.ACTION_UP:
				//回到初始位置
				mHeadView.setPadding(0,-1*mHeadView_height,0, 0);
				break;	
		}
		return true;
	}

	//这个方法是用来测量下拉头的高度的,我也不是很懂,反正直接用就行
	private void measureView(View child) {  
        ViewGroup.LayoutParams params = child.getLayoutParams();  
        if (params == null) {  
            params = new ViewGroup.LayoutParams(  
                    ViewGroup.LayoutParams.MATCH_PARENT,  
                    ViewGroup.LayoutParams.WRAP_CONTENT);  
        }  
        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0,  
                params.width);  
        int lpHeight = params.height;  
        int childHeightSpec;  
        if (lpHeight > 0) {  
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,  
                    MeasureSpec.EXACTLY);  
        } else {  
            childHeightSpec = MeasureSpec.makeMeasureSpec(0,  
                    MeasureSpec.UNSPECIFIED);  
        }  
        child.measure(childWidthSpec, childHeightSpec);  
    }  
	
}

MainActivity使用的布局文件

acitvity_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.example.ddddddddddd.CustomView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/listView" />
    
</LinearLayout>
其中com.example.ddddddddddd是我使用的包名,这里是一个自定义的控件

MainActivity.java

package com.example.ddddddddddd;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		//CustomView是自定义的类
		CustomView view=(CustomView) findViewById(R.id.listView);
		String[] item={"AAAAA","BBBBB","CCCCC","DDDDD","EEEEE","FFFFF"};
		ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,
				android.R.layout.simple_expandable_list_item_1,
				item);
		view.setAdapter(adapter);
	}
	
}

代码不算很多,慢慢看吧,有问题的可以在下面评论,过段时间我再把高级点的下拉刷新写出来




2017-09-02 16:02:57 qq_34819586 阅读数 433
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21619 人正在学习 去看看 李忠义

转载请注明出处:http://blog.csdn.net/qq_34819586

使用xlistview来进行 上拉加载更多、下拉刷新列表以及实现列表中图片的异步加载

参考文章:http://blog.csdn.net/afanbaby/article/details/55804850

http://blog.csdn.net/carterjin/article/details/7995935

附上:xListView的实现原理与解析http://blog.csdn.net/zhaokaiqiang1992/article/details/42392731

新手,首次写博客若有侵权请告知立刻删除文章。若有错误请多多指教。

效果图:网络差时会先用app内置图片

网络差时会先用app内置图片

 

 

 

 

MainActivity:

 

 

public class MainActivity extends Activity implements XListView.IXListViewListener {

    private XListView mListView;
    private Handler mHandler;
    private MyAdapter myAdapter;
    List<ImageEntry> mList;
	//要显示的参数及图片地址
    public String[] urls = new String[]{"http://img4.imgtn.bdimg.com/it/u=294550341,4259963231&fm=27&gp=0.jpg","http://img4.imgtn.bdimg.com/it/u=1037574783,2132354437&fm=27&gp=0.jpg"};
    public String[] time = new  String[]{"2017.08.01 11.11","2017.08.10 11.2"};
    public   Long[] id =new  Long[]{3L,4L};
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = (XListView) findViewById(R.id.xlistview);
        //mainAdapter = new MainAdapter(this);//实例化一个适配器对象
        //实例化一个图片数组列表对象
        mList = new ArrayList<ImageEntry>();
        //datas = new ArrayList<>();
        mHandler = new Handler();
        //设置数据
        geneItems();
        //为xListView设置一些配置和适配器
        mListView.setPullLoadEnable(true);
        mListView.setAdapter(myAdapter);
        mListView.setXListViewListener(this);


        //设置item的点击事件
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                //这里的i-1,是因为头视图占了一个position
                //Toast.makeText(MainActivity.this, "i:" + (i - 1), Toast.LENGTH_SHORT).show();
				
				
                //这里我修改为显示items的id,在MyAdapter的getItemId处修改
                Toast.makeText(MainActivity.this, "你点击的item的id是:" +l, Toast.LENGTH_SHORT).show();
            }
        });
        //设置长按事件
        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(MainActivity.this, "长按事件 i:" + (i-1), Toast.LENGTH_SHORT).show();
                return false;
            }
        });

        /*
        //添加头布局
        View view = getLayoutInflater().inflate(R.layout.head_view, null);
        mListView.addHeaderView(view);
        //添加尾视图
        View view2 = getLayoutInflater().inflate(R.layout.head_view, null);
        mListView.addFooterView(view2);
        */

        //设置禁止上拉
        //mListView.setPullLoadEnable(false);
        //设置禁止下拉
        //mListView.setPullRefreshEnable(false);

    }

//为图片数组列表设置值并为适配器传递数组列表即传递数据,且还实例化了一个myAdapt对象
private void geneItems() {
    for(int i=0; i<2; i++){
        ImageEntry entry = new ImageEntry();
        entry.seturl(urls[i]);//为ImageEntry中url赋值
        entry.settime(time[i]);
        entry.setid(id[i]);
        mList.add(entry);
    }
    myAdapter = new MyAdapter(this,mList);
    //为MyAdapter中xlist_v赋值
    myAdapter.SetXListView(mListView);
}



    //下拉刷新
    @Override
    public void onRefresh() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                
                mList.clear();//清空数组列表变量
                geneItems();
                
                mListView.setAdapter(myAdapter);
                onLoad();
            }
        }, 2000);
    }

    //上拉加载
    @Override
    public void onLoadMore() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                geneItems();
                //mainAdapter.notifyDataSetChanged();
                myAdapter.notifyDataSetChanged();
                onLoad();
            }
        }, 2000);
    }

//停止更新和加载并重置头尾部view。获取时间。
    private void onLoad() {
        mListView.stopRefresh();
        mListView.stopLoadMore();
        //获取当前时间
        Date curDate = new Date(System.currentTimeMillis());
        //格式化
        SimpleDateFormat formatter = new SimpleDateFormat();
        String time = formatter.format(curDate);
        mListView.setRefreshTime(time);
}
}

 

AsyncImageLoader :

 

/**
 * 异步加载图片类,内部有缓存,可以通过后台线程获取网络图片。首先生成一个实例,并调用loadDrawableByTag方法来获取一个Drawable对象
 */
public class AsyncImageLoader {

    /**
     * 使用软引用SoftReference,可以由系统在恰当的时候更容易的回收
     */
    private HashMap<String, SoftReference<Drawable>> imageCache;


    public AsyncImageLoader(){
        imageCache = new HashMap<String, SoftReference<Drawable>>();
    }




    /**
     * 通过传入的TagInfo来获取一个网络上的图片
     * @param tag TagInfo对象,保存了position、url和一个待获取的Drawable对象
     * @param callback ImageCallBack对象,用于在获取到图片后供调用侧进行下一步的处理
     * @return drawable 从网络或缓存中得到的Drawable对象,可为null,调用侧需判断
     */
    public Drawable loadDrawableByTag(final TagInfo tag, final ImageCallBack callback){
        Drawable drawable;

        /**
         * 先在缓存中找,如果通过URL地址可以找到,则直接返回该对象
         */
        if(imageCache.containsKey(tag.getUrl())){
            drawable = imageCache.get(tag.getUrl()).get();
            if(null!=drawable){
                return drawable;
            }
        }


        /**
         * 用于在获取到网络图片后,保存图片到缓存,并触发调用侧的处理
         */
        final Handler handler = new Handler(){

            @Override
            public void handleMessage(Message msg) {

                TagInfo info = (TagInfo)msg.obj;
                imageCache.put(info.url, new SoftReference<Drawable>(info.drawable));
                callback.obtainImage(info);

                super.handleMessage(msg);
            }

        };


        /**
         * 如果在缓存中没有找到,则开启一个线程来进行网络请求
         */
        new Thread(new Runnable() {

            @Override
            public void run() {

                TagInfo info = getDrawableIntoTag(tag);
                Message msg = new Message();
                msg.what = 0;
                msg.obj = info;
                handler.sendMessage(msg);
            }
        }).start();

        return null;
    }



    /**
     * 通过传入的TagInfo对象,利用其URL属性,到网络请求图片,获取到图片后保存在TagInfo的Drawable属性中,并返回该TagInfo
     * @param info TagInfo对象,需要利用里面的url属性
     * @return TagInfo 传入的TagInfo对象,增加了Drawable属性后返回
     */
    public TagInfo getDrawableIntoTag(TagInfo info){
        URL request;
        InputStream input;
        Drawable drawable = null;

        try{
            request = new URL(info.getUrl());
            input = (InputStream)request.getContent();
            drawable = Drawable.createFromStream(input, "src"); // 第二个属性可为空,为DEBUG下使用,网上的说明
        }
        catch(Exception e){
            e.printStackTrace();
        }

        info.drawable = drawable;
        return info;
    }



    /**
     * 获取图片的回调接口,里面的obtainImage方法在获取到图片后进行调用
     */
    //interface类是让别的类继承的,如果没有类继承就没意义了,所以你不能用private(私有的)、protected(受保护的)来修饰它。如果修饰了别的类都没法继承它啦,就没意义啦interface类是让别的类继承的,如果没有类继承就没意义了,所以你不能用private(私有的)、protected(受保护的)来修饰它。如果修饰了别的类都没法继承它啦,就没意义啦
    interface ImageCallBack{
        /**
         * 获取到图片后在调用侧执行具体的细节
         * @param info TagInfo对象,传入的info经过处理,增加Drawable属性,并返回给传入者
         */
        public void obtainImage(TagInfo info);
    }



}

 

ImageEntry:

 

/**
 * 一个ImageEntry代表了一个带有图片地址url等其他属性的实例,为提高可扩展性,封装了一个对象。
 */
public  class ImageEntry{
    String url;
    String name;
    String time;
    String title;
    Long id;
    public String getUrl(){
        return this.url;
    }
    public String getName(){
        return this.name;
    }
    public String getTime(){
        return this.time;
    }
    public String getTitle(){
        return this.title;
    }
    public Long getId(){
        return this.id;
    }

    public void setid(Long id){
        this.id = id;
    }
    public void seturl(String url){
        this.url = url;
    }
    public void settime(String time){
        this.time = time;
    }
    public void settitle(String title){
        this.title = title;
    }

}

 

MyAdapter:

 


 
/**
 * 重写的Adapter
 */
public  class MyAdapter extends BaseAdapter {

    Context context;
    List<ImageEntry> mList;
    XListView xlist_lv;

    HashMap<String, Drawable> imgCache;     // 图片缓存
    HashMap<Integer, TagInfo> tag_map;      // TagInfo缓存
    AsyncImageLoader loader;                // 异步加载图片类



    /**
     * 构造函数
     * @param context 上下文
     * @param list 包含了所有要显示的图片的ImageEntry对象的列表
     */
    public MyAdapter(Context context, List<ImageEntry> list){
        this.context = context;
        this.mList = list;
        imgCache = new HashMap<String, Drawable>();
        loader = new AsyncImageLoader();
        tag_map = new HashMap<Integer, TagInfo>();

    }

    //获取当前items项的大小,也可以看成是数据源的大小
    //getCount决定了listview一共有多少个item
    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mList.size();
    }
    //根据item的下标获取到View对象
    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return mList.get(position);
    }
    //获取到items的id,对应onItemClick中long的na参数
    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return mList.get(position).getId();
       // return 0;
    }

    //根据传入item的下标,获取到view对象
        /*
         * int position,      表示item所在listView中的下标,也是在数据源中下标所对应的数据
         * View convertView,  缓存机制,当一些item项滑出屏幕的时候,会创建新的View对象,这样会使得内存资源占据,
         *                                  所以使用convertView判断是否为空,如果为空的说明item没有滑出,需要创建新的view对象
         *                          如果不为空,说明已经滑出类屏幕所以使用convertView ,view = convertView,
         *                                  可以把convert 理解为滑出的view对象
         * ViewGroup parent   视图组对象,即 表示当前绘制的items项所属的ListView对象。
         * */
    //getView返回了每个item项所显示的view
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        ViewHolder holder = null;

        if(null==convertView){
            convertView = LayoutInflater.from(context).inflate(R.layout.item, null, false);
            holder = new ViewHolder();
            holder.img = (ImageView) convertView.findViewById(R.id.logo);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }


        String imgurl = mList.get(position).getUrl();   // 得到该项所代表的url地址
        Drawable drawable = imgCache.get(imgurl);       // 先去缓存中找

        TagInfo tag = new TagInfo();
        tag.setPosition(position);  // 保存了当前在adapter中的位置
        tag.setUrl(imgurl);         // 保存当前项所要加载的url
        holder.img.setTag(tag);     // 为ImageView设置Tag,为以后再获取图片后好能找到它
        tag_map.put(position, tag); // 把该TagInfo对应position放入Tag缓存中

        //为列表的文本赋值
        //TextView ItemName = (TextView) convertView.findViewById(R.id.name);
        //ItemName.setText(mList.get(position).getName());
        TextView ItemTime = (TextView) convertView.findViewById(R.id.time);
        ItemTime.setText(mList.get(position).getTime());
        //TextView ItemTitle = (TextView) convertView.findViewById(R.id.title);
        //ItemTitle.setText(mList.get(position).getTitle());


        if(null!=drawable){                         // 找到了直接设置为图像
            holder.img.setImageDrawable(drawable);
        }else{                                      // 没找到则开启异步线程
            drawable = loader.loadDrawableByTag(tag, new ImageCallBack() {

                @Override
                public void obtainImage(TagInfo ret_info) {

                    imgCache.put(ret_info.getUrl(), ret_info.getDrawable());    // 首先把获取的图片放入到缓存中
                    // 通过返回的TagInfo去Tag缓存中找,然后再通过找到的Tag来获取到所对应的ImageView
                    ImageView tag_view = (ImageView) xlist_lv.findViewWithTag(tag_map.get(ret_info.getPosition()));
                    Log.i("carter", "tag_view: " + tag_view + " position: " + ret_info.getPosition());
                    if(null!=tag_view)
                    {
                        tag_view.setImageDrawable(ret_info.getDrawable());
                        notifyDataSetChanged();//这样可以在fragement中实现 异步更新图片
                    }
                }
            });


            if(null==drawable){ // 如果获取的图片为空,则默认显示一个图片
                holder.img.setImageResource(R.drawable.nv);

            }
        }


        return convertView;
    }



    class ViewHolder{
        ImageView img;
    }

    public void SetXListView(XListView XListView){
        this.xlist_lv=XListView;
    }

}

 

TagInfo

 

public class TagInfo {
    String url;
    int position;
    Drawable drawable;

    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public int getPosition() {
        return position;
    }
    public void setPosition(int position) {
        this.position = position;
    }
    public Drawable getDrawable() {
        return drawable;
    }
    public void setDrawable(Drawable drawable) {
        this.drawable = drawable;
    }

}


view中的3个java可以去github下载我项目中没有修改过:

https://github.com/Maxwin-z/XListView-Android
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.what.xlistview.MainActivity">

    <com.example.what.xlistview.view.XListView
        android:id="@+id/xlistview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cacheColorHint="#00000000"
        android:scrollbars="none" />

</RelativeLayout>

 


item.xml:

 

 

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/box1"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <RelativeLayout
        android:id="@+id/box2"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        >
        <LinearLayout
            android:id="@+id/textbox"
            android:layout_width="280dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:orientation="horizontal"
            >
            <ImageView
                android:id="@+id/photo"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginLeft="10dp"
                />
            <TextView
                android:id="@+id/name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="5dp"
                android:textSize="16dp"
                />
            <TextView
                android:id="@+id/time"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:layout_marginLeft="10dp"
                android:textSize="12dp"
                android:layout_marginTop="5dp"
                android:textColor="#999"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="280dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textbox"
            android:layout_marginTop="15dp"
            >
            <TextView
                android:id="@+id/title"
                android:layout_width="230dp"
                android:layout_height="60dp"
                android:layout_marginLeft="10dp"
                />
        </LinearLayout>
        <ImageView
            android:id="@+id/logo"
            android:layout_width="100dp"
            android:layout_height="80dp"
            android:layout_marginTop="20dp"
            android:layout_marginRight="10dp"
            android:layout_alignParentRight="true"
            />
    </RelativeLayout>
</RelativeLayout>


head_view.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"
    android:orientation="vertical">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="@drawable/headiv" />

</LinearLayout>

 

xlistview_footer.xml和xlistview_header.xml,strings.xml也是github中的

 

权限方面只要有  <uses-permissionandroid:name="android.permission.INTERNET"/>

项目下载地址:http://download.csdn.net/download/qq_34819586/9961558

 

2016-08-12 20:28:41 qq_34908107 阅读数 267
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21619 人正在学习 去看看 李忠义
Pulltorefresh实现ListView下拉刷新,上拉加载
在做android项目的时候,我们经常要用到上拉刷新列表,下拉刷新列表的功能,这里简单介绍一个PullToRefresh的使用。

  一,下载PullToRefresh,地址:https://github.com/chrisbanes/Android-PullToRefresh。这里面,我们只要其中的Library工程。将它引入我们的工程.


需要的话可以下载我的demo:     地址:Listview_pulltorefreshDEMO


效果图:





















布局如下:

<span style="font-size:18px;"><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" >

    <com.handmark.pulltorefresh.library.PullToRefreshListView
        xmlns:ptr="http://schemas.android.com/apk/res-auto"
        android:id="@+id/pull_refresh_list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:cacheColorHint="#00000000"
        android:divider="#19000000"
        android:dividerHeight="4dp"
        android:fadingEdge="none"
        android:fastScrollEnabled="false"
        android:footerDividersEnabled="false"
        android:headerDividersEnabled="false"
        android:smoothScrollbar="true"
        ptr:ptrListViewExtrasEnabled="false"
        ptr:ptrAnimationStyle="flip"
        ptr:ptrMode="both"
        ptr:ptrScrollingWhileRefreshingEnabled="true" >
    </com.handmark.pulltorefresh.library.PullToRefreshListView>

</RelativeLayout></span>

Activity的逻辑如下:

<span style="font-size:18px;">package com.example.zhy_pulltorefreash_chenyoca;

import java.util.LinkedList;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener2;
import com.handmark.pulltorefresh.library.PullToRefreshListView;

public class PullToRefreshListActivity extends Activity
{

	private LinkedList<String> mListItems;
	/**
	 * 上拉刷新的控件
	 */
	private PullToRefreshListView mPullRefreshListView;

	private ArrayAdapter<String> mAdapter;

	private int mItemCount = 15;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// 得到控件
		mPullRefreshListView = (PullToRefreshListView) findViewById(R.id.pull_refresh_list);
		mPullRefreshListView.setMode(Mode.BOTH);
		// 初始化数据
		initDatas();
		// 设置适配器
		mAdapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, mListItems);
		mPullRefreshListView.setAdapter(mAdapter);

		mPullRefreshListView
				.setOnRefreshListener(new OnRefreshListener2<ListView>()
				{
					@Override
					public void onPullDownToRefresh(
							PullToRefreshBase<ListView> refreshView)
					{
						Log.e("TAG", "onPullDownToRefresh");
						//这里写下拉刷新的任务
						new GetDataTask().execute();
					}

					@Override
					public void onPullUpToRefresh(
							PullToRefreshBase<ListView> refreshView)
					{
						Log.e("TAG", "onPullUpToRefresh");
						//这里写上拉加载更多的任务
						new GetDataTask().execute();
					}
				});

	}

	private void initDatas()
	{
		// 初始化数据和数据源
		mListItems = new LinkedList<String>();

		for (int i = 0; i < mItemCount; i++)
		{
			mListItems.add("" + i);
		}
	}

	private class GetDataTask extends AsyncTask<Void, Void, String>
	{

		@Override
		protected String doInBackground(Void... params)
		{
			try
			{
				Thread.sleep(2000);
			} catch (InterruptedException e)
			{
			}
			return "" + (mItemCount++);
		}

		@Override
		protected void onPostExecute(String result)
		{
			mListItems.add(result);
			mAdapter.notifyDataSetChanged();
			// Call onRefreshComplete when the list has been refreshed.
			mPullRefreshListView.onRefreshComplete();
		}
	}

	/**
	 * // 设置监听事件 mPullRefreshListView .setOnRefreshListener(new
	 * OnRefreshListener<ListView>() {
	 * 
	 * @Override public void onRefresh( PullToRefreshBase<ListView> refreshView)
	 *           { String label = DateUtils.formatDateTime(
	 *           getApplicationContext(), System.currentTimeMillis(),
	 *           DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
	 *           DateUtils.FORMAT_ABBREV_ALL); // 显示最后更新的时间
	 *           refreshView.getLoadingLayoutProxy()
	 *           .setLastUpdatedLabel(label);
	 * 
	 *           // 模拟加载任务 new GetDataTask().execute(); } });
	 */

}
</span>













做一个类似qq客户端好友动态刷新的

博文 来自: summertime2013
没有更多推荐了,返回首页