天气预报中下拉刷新和左右切换

实现下拉刷新和左右切换,思路比较简单就是在ViewPager中的每个页面中加个下拉刷新ScrollView。但是ViewPager和ScrollView就会有冲突。所有我们要自定义个ViewPager,

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * 此ViewPager解决与父容器ScrollView冲突的问题,无法完美解决.有卡顿 此自定义组件和下拉刷新scrollview配合暂时小完美,有待改善
 * 
 * @author bavariama
 * 
 */
public class weatherViewPager extends ViewPager {

	float x, y;
	boolean flag;
	OnSingleTouchListener onSingleTouchListener;

	public weatherViewPager(Context context) {
		// TODO Auto-generated constructor stub
		super(context);
	}

	public weatherViewPager(Context context, AttributeSet attrs) {
		// TODO Auto-generated constructor stub
		super(context, attrs);
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			getParent().requestDisallowInterceptTouchEvent(false);
			if (!flag) {
				x = ev.getX();
				y = ev.getY();
			}
		} else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
			if (!flag) {
				float k = Math.abs((ev.getY()-y) / (ev.getX() - x));
				getParent().requestDisallowInterceptTouchEvent(ev.getY()<y&&k<1);
				flag = true;
			}
		} else {
			flag = false;
			getParent().requestDisallowInterceptTouchEvent(false);
		}
		
		
		return super.onTouchEvent(ev);
	}

	public void onSingleTouch() {
		if (onSingleTouchListener != null) {
			onSingleTouchListener.onSingleTouch();
		}
	}

	public interface OnSingleTouchListener {
		public void onSingleTouch();
	}

	public void setOnSingleTouchListner(
			OnSingleTouchListener onSingleTouchListener) {
		this.onSingleTouchListener = onSingleTouchListener;
	}

}

下拉刷新自定义View

import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;

public class DropLayout extends LinearLayout {

	private ScrollView sc;
	private LayoutInflater inflater;
	private LinearLayout header;
	private ImageView arrowImg;
	private ProgressBar headProgress;
	private TextView lastUpdateTxt;
	private TextView tipsTxt;
	private RotateAnimation tipsAnimation;
	private RotateAnimation reverseAnimation;
	private int headerHeight; // 头高度
	private int lastHeaderPadding; // 最后一次调用Move Header的Padding
	private boolean isBack; // 从Release 转到 pull
	private int headerState = DONE;
	private RefreshCallBack callBack;
	private LinearLayout subLayout;

	static final private int RELEASE_To_REFRESH = 0;
	static final private int PULL_To_REFRESH = 1;
	static final private int REFRESHING = 2;
	static final private int DONE = 3;

	public DropLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	private void init(Context context) {
		inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		sc = new ScrollView(context);
		sc.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT));
		// 由于ScrollView 只允许有一个ChildView所以再用LinearLayout来做容器
		subLayout = new LinearLayout(context);
		subLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
				LayoutParams.WRAP_CONTENT));
		subLayout.setOrientation(VERTICAL);
		sc.addView(subLayout);
		header = (LinearLayout) inflater.inflate(R.layout.drag_drop_header,
				null);
		measureView(header);
		headerHeight = header.getMeasuredHeight();
		lastHeaderPadding = (-1 * headerHeight); // 最后一次调用Move Header的Padding
		header.setPadding(0, lastHeaderPadding, 0, 0);
		header.invalidate();
		this.addView(header, 0);
		this.addView(sc, 1);

		headProgress = (ProgressBar) findViewById(R.id.head_progressBar);
		arrowImg = (ImageView) findViewById(R.id.head_arrowImageView);
		arrowImg.setMinimumHeight(50);
		arrowImg.setMinimumWidth(50);
		tipsTxt = (TextView) findViewById(R.id.head_tipsTextView);
		lastUpdateTxt = (TextView) findViewById(R.id.head_lastUpdatedTextView);
		// 箭头转动动画
		tipsAnimation = new RotateAnimation(0, -180,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		tipsAnimation.setInterpolator(new LinearInterpolator());
		tipsAnimation.setDuration(200); // 动画持续时间
		tipsAnimation.setFillAfter(true); // 动画结束后保持动画
		// 箭头反转动画
		reverseAnimation = new RotateAnimation(-180, 0,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		reverseAnimation.setInterpolator(new LinearInterpolator());
		reverseAnimation.setDuration(200);
		reverseAnimation.setFillAfter(true);
		// 为scrollview绑定事件
		sc.setOnTouchListener(new OnTouchListener() {
			private int beginY;

			@Override
			public boolean onTouch(View v, MotionEvent event) {

				switch (event.getAction()) {
				case MotionEvent.ACTION_MOVE:
					
					if ((sc.getScrollY() == 0 || lastHeaderPadding > (-1 * headerHeight))
							&& headerState != REFRESHING) {
						// 拿到滑动的Y轴距离
						int interval = (int) (event.getY() - beginY);
						// 是向下滑动而不是向上滑动
						if (interval > 0) {
							interval = interval / 2;// 下滑阻力
							lastHeaderPadding = interval + (-1 * headerHeight);
							header.setPadding(0, lastHeaderPadding, 0, 0);
							if (lastHeaderPadding > 0) {
								// txView.setText("我要刷新咯");
								headerState = RELEASE_To_REFRESH;
								// 是否已经更新了UI
								if (!isBack) {
									isBack = true; // 到了Release状态,如果往回滑动到了pull则启动动画
									changeHeaderViewByState();
								}
							} else {
								headerState = PULL_To_REFRESH;
								changeHeaderViewByState();
								
							}
						}
					}
					break;
				case MotionEvent.ACTION_DOWN:
					// 加上下滑阻力与实际滑动距离的差(大概值)
					beginY = (int) ((int) event.getY() + sc.getScrollY() * 1.5);
					break;
				case MotionEvent.ACTION_UP:
					if (headerState != REFRESHING) {
						switch (headerState) {
						case DONE:
							// 什么也不干
							break;
						case PULL_To_REFRESH:
							headerState = DONE;
							lastHeaderPadding = -1 * headerHeight;
							header.setPadding(0, lastHeaderPadding, 0, 0);
							changeHeaderViewByState();
							break;
						case RELEASE_To_REFRESH:
							isBack = false; // 准备开始刷新,此时将不会往回滑动
							headerState = REFRESHING;
							changeHeaderViewByState();
							onRefresh();
							break;
						default:
							break;
						}
					}
					break;
				}
				// 如果Header是完全被隐藏的则让ScrollView正常滑动,让事件继续否则的话就阻断事件
				if (lastHeaderPadding > (-1 * headerHeight)
						&& headerState != REFRESHING) {
					return true;
				} else {
					return false;
				}
			}
		});
	}

	@Override
	public void addView(View child, int index,
			android.view.ViewGroup.LayoutParams params) {
		// 读取XML中的默认给 -1 自己添加的为0 和 1
		if (index == -1) {
			subLayout.addView(child, params);
			return;
		}
		super.addView(child, index, params);
	}
	//下拉刷新接口
	public void setRefreshCallBack(RefreshCallBack callBack) {
		this.callBack = callBack;
	}

	private void changeHeaderViewByState() {
		switch (headerState) {
		case PULL_To_REFRESH:
			// 是由RELEASE_To_REFRESH状态转变来的
			if (isBack) {
				isBack = false;
				arrowImg.startAnimation(reverseAnimation);
				tipsTxt.setText(getResources().getString(
						R.string.pull_down_to_refresh));
			}
			tipsTxt.setText(getResources().getString(
					R.string.pull_down_to_refresh));
			break;
		case RELEASE_To_REFRESH:
			arrowImg.setVisibility(View.VISIBLE);
			headProgress.setVisibility(View.GONE);
			tipsTxt.setVisibility(View.VISIBLE);
			lastUpdateTxt.setVisibility(View.VISIBLE);
			arrowImg.clearAnimation();
			arrowImg.startAnimation(tipsAnimation);
			tipsTxt.setText(getResources().getString(
					R.string.loosen_the_refresh));
			break;
		case REFRESHING:
			lastHeaderPadding = 0;
			header.setPadding(0, lastHeaderPadding, 0, 0);
			header.invalidate();
			headProgress.setVisibility(View.VISIBLE);
			arrowImg.clearAnimation();
			arrowImg.setVisibility(View.INVISIBLE);
			tipsTxt.setText(getResources().getString(R.string.refreshing));
			lastUpdateTxt.setVisibility(View.VISIBLE);
			break;
		case DONE:
			lastHeaderPadding = -1 * headerHeight;
			header.setPadding(0, lastHeaderPadding, 0, 0);
			header.invalidate();
			headProgress.setVisibility(View.GONE);
			arrowImg.clearAnimation();
			arrowImg.setVisibility(View.VISIBLE);
			tipsTxt.setText(getResources().getString(
					R.string.pull_down_to_refresh));
			lastUpdateTxt.setVisibility(View.VISIBLE);
			break;
		default:
			break;
		}
	}

	private void onRefresh() {
		new RefreshAsyncTask().execute();
	}

	private class RefreshAsyncTask extends AsyncTask<Void, Void, Void> {
		protected Void doInBackground(Void... params) {
			if (callBack != null) {
				callBack.doInBackground();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			onRefreshComplete();
			if (callBack != null) {
				callBack.complete();
			}
		}
	}

	public interface RefreshCallBack {
		public void doInBackground();

		public void complete();
	}

	@SuppressWarnings("deprecation")
	public void onRefreshComplete() {
		headerState = DONE;
		lastUpdateTxt.setText(getResources().getString(
				R.string.the_recently_updated)
				+ new Date().toLocaleString());
		changeHeaderViewByState();
	}

	// 由于OnCreate里面拿不到header的高度所以需要手动计算
	private void measureView(View childView) {
		android.view.ViewGroup.LayoutParams p = childView.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}
		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int height = p.height;
		int childHeightSpec;
		if (height > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(height,
					MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0,
					MeasureSpec.UNSPECIFIED);
		}
		childView.measure(childWidthSpec, childHeightSpec);
	}
}


由于天气每个页面的布局是一样的,数据不一样。所以我们可以自定义布局在自定义布局类中设置数据

public class WeatherLinearLayout extends LinearLayout {
	private LayoutInflater inflater;
	private Context context;
	private View cityView;
	private WeatherData tempData;
	private DropLayout dropLayout;
	private int index;

	private WeatherLinearLayout(Context context) {
		super(context);

	}

	public WeatherLinearLayout(Context context, int index) {
		super(context);
		this.context = context;
		this.index = index;
		inflater = LayoutInflater.from(context);
		//存储天气数据
		tempData = WeatherData.getInstance(context);
		//获取list中的每一页的数据
		View view = createCityView(tempData.getWidgetEntity(index));
		addView(view);
	}
	//获取城市布局和数据展示
	private View createCityView(WeatherEntity wEntity) {
		cityView = inflater.inflate(R.layout.city_weather_data_display, null);
		findAndSetWeatherView(wEntity, cityView);
		return cityView;
	}

	// 由城市码设置天气情况
	public void findAndSetWeatherView(WeatherEntity wEntity, View weatherView) {
		TextView tempText = null;
		ImageView imageView = null;
	
		//下拉刷新控件
		dropLayout = (DropLayout) weatherView
				.findViewById(R.id.refreshscrollview);
		//实现刷新接口
		dropLayout.setRefreshCallBack(new RefreshCallBack() {

			@Override
			public void doInBackground() {
				//在这里处理具体的刷新内容
				.............
			}

			@Override
			public void complete() {
				//判断是否刷新成功
				if (WeatherData.getInstance(context).getWidgetEntity(index)
						.getCurrentTemp() == null) {

					Toast.makeText(context,
							R.string.network_connection_fails_tips,
							Toast.LENGTH_LONG).show();
					return;
				}
				// 更新数据
				findAndSetWeatherView(tempData.getWidgetEntity(index), cityView);
				
			}
		});
		// 发布时间
		tempText = (TextView) weatherView
				.findViewById(R.id.cityview_public_time);
		tempText.setText(wEntity.getObservation_time()
				+ context.getResources().getString(R.string.update_time));
		// 日出日落时间
		tempText = (TextView) weatherView.findViewById(R.id.sunrise);
		tempText.setText(context.getResources().getString(R.string.sunrise)
				+ " " + wEntity.getDate0().getSunrise());
		tempText = (TextView) weatherView.findViewById(R.id.sunset);
		tempText.setText(context.getResources().getString(R.string.sunset)
				+ " " + wEntity.getDate0().getSunset());

		 // 当前温度
		 tempText = (TextView) weatherView.findViewById(R.id.cityview_temp);
		 tempText.setText(wEntity.getCurrentTemp() + "°");
		
		....................
	}


}


布局文件需要注意的已标注

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/weather_background_image"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <yong.desk.weather.DropLayout
        android:id="@+id/refreshscrollview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <LinearLayout
            android:id="@+id/layout_city_view_root"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
			<!-- 这里一定要用相对布局不然数据展示有问题 -->
            <RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" >

                <TextView
                    android:id="@+id/cityview_public_time"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dip"
                    android:textColor="@color/white"
                    android:textSize="@dimen/font_size_small" />
            </RelativeLayout>

            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="100dip" >               
                    <TextView
                        android:id="@+id/sunrise"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="10dip"
                        android:text="2015/04/17"
                        android:textColor="@color/white"
                        android:textSize="@dimen/font_size_big" />

                    <TextView
                        android:id="@+id/sunset"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="10dip"
                        android:layout_marginTop="4dip"
                        android:textColor="@color/white"
                        android:textSize="@dimen/font_size_big" />    
					<TextView
                        android:id="@+id/cityview_temp"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="10dip"
                        android:layout_marginTop="4dip"
                        android:textColor="@color/white"
                        android:textSize="@dimen/font_size_big" />  						
            </LinearLayout>          
        </LinearLayout>
    </yong.desk.weather.DropLayout>

</LinearLayout>

主活动的调用

public class MainActivity extends Activity implements OnClickListener,
		OnPageChangeListener {
	
	private FrameLayout rootLayout;
	private weatherViewPager viewPager;
	private MyAdapter mPagerAdapter;
	private ArrayList<View> pageViews;
	private ImageView[] tips;
	private ImageView cityManager;
	private TextView cityNameView;
	private ImageView shareImageView;
	private ImageView menuImageView;

	private ViewGroup group;
	private int position;
	private long exitTime = 0;
	private boolean isCityList = true;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		Log.e("MainActivity", "onCreate");
		super.onCreate(savedInstanceState);				
		setContentView(R.layout.layout_weather_main);	
		initView();
		// 获取数据
		getData();
	}

	private void initView() {
		rootLayout = (FrameLayout) findViewById(R.id.frameLayout_main);
		// 城市管理按钮
		cityManager = (ImageView) findViewById(R.id.title_city_manager);
		cityManager.setOnClickListener(this);
		cityNameView = (TextView) findViewById(R.id.actionbar_city_name);
		cityNameView.setOnClickListener(this);
		// 分享按钮
		shareImageView = (ImageView) findViewById(R.id.title_share);
		shareImageView.setOnClickListener(this);
		// meun按钮
		menuImageView = (ImageView) findViewById(R.id.title_menu);
		menuImageView.setOnClickListener(this);
		viewPager = (weatherViewPager) findViewById(R.id.viewPager);
		//添加标注点
		group = (ViewGroup) findViewById(R.id.viewGroup);
		pageViews = new ArrayList<View>();
	}

	private void getData() {
		//获取list中有几页数据
		tips = new ImageView[WeatherData.getInstance(this)
				.getWidgetEntityListCount()];
		group.removeAllViews();
		//添加标注点
		for (int i = 0; i < tips.length; i++) {
			ImageView imageView = new ImageView(this);
			imageView.setLayoutParams(new LayoutParams(10, 10));
			tips[i] = imageView;
			if (i == 0) {
				tips[i].setBackgroundResource(R.drawable.page_indicator_focused);
			} else {
				tips[i].setBackgroundResource(R.drawable.page_indicator_unfocused);
			}

			LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
					new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,
							LayoutParams.WRAP_CONTENT));
			layoutParams.leftMargin = 5;
			layoutParams.rightMargin = 5;
			group.addView(imageView, layoutParams);
		}
		pageViews.clear();
		//添加数据存储到pageViews<View>的集合中再通过适配器展示
		for (int i = 0; i < tips.length; i++) {
			pageViews.add(new WeatherLinearLayout(this, i));
		}
		mPagerAdapter = new MyAdapter();
		viewPager.setAdapter(mPagerAdapter);
		viewPager.setOnPageChangeListener(this);
		//指定显示那一页
		viewPager.setCurrentItem(0);  		

	}	

	@Override
	public void onClick(View arg0) {
		Intent intent = null;
		switch (arg0.getId()) {
		case R.id.title_city_manager:
			// 跳转到设置城市的Activity
			
			break;
		case R.id.title_city_name:
			// 跳转到设置城市的Activity
			
			break;
		case R.id.title_share:
		//跳转到分享的Activity
			String weatherShare = WeatherData.getInstance(this)
					.formatCurWeatherToStirng();
			if (weatherShare == null) {
				Toast.makeText(this, R.string.not_set_city_tips,
						Toast.LENGTH_LONG).show();
				return;
			}
			intent = new Intent(Intent.ACTION_SEND);
			intent.setType("text/plain");
			intent.putExtra(Intent.EXTRA_SUBJECT, R.string.share_weather);
			intent.putExtra(Intent.EXTRA_TEXT, weatherShare);
			startActivity(Intent.createChooser(intent, getTitle()));
			break;
		case R.id.title_menu:
			// 跳转到帮助的Activity
			
			break;
		default:
			break;
		}
	}
	

	@Override
	public void onPageScrollStateChanged(int arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onPageScrolled(int arg0, float arg1, int arg2) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onPageSelected(int arg0) {
		//ViewPager页面变化改变标注点
		setImageBackground(arg0 % pageViews.size());
		if (arg0 > pageViews.size() - 1) {
			return;
		} else {
			//设置城市名字
			WorkspaceProxy.getInstance().changeCityTitle(
					WeatherData.getInstance(this)
							.getWidgetEntity(arg0)
							.getCityName());
		}
	}

	/**
	 * 设置选中的tip的背景
	 * 
	 * @param selectItems
	 */
	private void setImageBackground(int selectItems) {
		for (int i = 0; i < tips.length; i++) {
			if (i == selectItems) {
				tips[i].setBackgroundResource(R.drawable.page_indicator_focused);
			} else {
				tips[i].setBackgroundResource(R.drawable.page_indicator_unfocused);
			}
		}
	}
	//ViewPager适配器
	public class MyAdapter extends PagerAdapter {

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

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			return arg0 == arg1;
		}

		@Override
		public void destroyItem(View container, int position, Object object) {
			Log.i("jjf", "destroyItem" + position);
			if (position > pageViews.size() - 1) {
				return;
			} else {
				((ViewPager) container).removeView(pageViews.get(position));
			}
		}

		/**
		 * 载入图片进去,用当前的position 除以 图片数组长度取余数是关键
		 */
		@Override
		public Object instantiateItem(View container, int position) {
			((ViewPager) container).addView(
					pageViews.get(position % pageViews.size()), 0);
			return pageViews.get(position % pageViews.size());
		}

	}
	
	//按俩下返回退出程序
	@Override
	public void onBackPressed() {
		if ((System.currentTimeMillis() - exitTime) > 2000) {
			Toast.makeText(getApplicationContext(),
					getString(R.string.exit_app), Toast.LENGTH_SHORT).show();
			exitTime = System.currentTimeMillis();
		} else {
			finish();
			System.exit(0);
		}
	}
}

希望能够帮助大家


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值