智慧北京总结

一.框架的使用

①.support-v4包下的ViewPager

vpGuide = (ViewPager) findViewById(R.id.vp_guide);
vpGuide.setAdapter(new MyPagerAdapter());// 设置适配器
vpGuide.setCurrentItem(Position)//设置Viewpager的位置
vpGuide.setOnPageChangeListener(new GuidePageListener());// 设置滑动监听

// pagerAdapter适配器
	class MyPagerAdapter extends PagerAdapter {

		@Override
		public int getCount() {
			return mImageIds.length;
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			return arg0 == arg1;
		}
		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			container.addView(imageViews.get(position));//添加VIew到Viewpager中
			return imageViews.get(position);
		}
		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView((View) object);//移除View
		}
	}
②.slideMenu框架,实现侧边栏(onViewdrap 也可以实现。qq侧边栏)


---导入SlideMenuLibrary包

---使用SlideMenu

<span style="white-space:pre">		</span>setBehindContentView(R.layout.left_menu);// 设置侧边栏
		SlidingMenu slidingMenu = getSlidingMenu();// 获取侧边栏对象
		slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);// 设置全屏触摸
		int width = getWindow().getWindowManager().getDefaultDisplay().getWidth();
		slidingMenu.setBehindOffset(width*2/3);// 设置contentFragment预留屏幕的宽度也就是侧边栏为3分之一屏幕宽度
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>/**是否隐藏左侧菜单页*/
<span style="white-space:pre">		</span>protected void toggleSlideMenu() {
<span style="white-space:pre">			</span>SlidingMenu slidingMenu = mainUi.getSlidingMenu();
<span style="white-space:pre">			</span>slidingMenu.toggle();//显示时隐藏 .隐藏时显示
<span style="white-space:pre">		</span>}

---填充Fragment到侧边栏中

<span style="white-space:pre">		</span>// 填充内容
		beginTransaction.replace(R.id.fl_left_menu, new LeftMenuFragment(),FRAGMENT_LEFT_MENU);
③.ViewPagerIndicatorLibrary框架(为Viewpager设置一个Tab栏)


---设置xml控件(放置在ViewPager的上方)

<span style="white-space:pre">	</span><com.viewpagerindicator.TabPageIndicator
            android:id="@+id/titles"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

              ---代码设置

<span style="white-space:pre">	</span>mIndicator = (TabPageIndicator) view.findViewById(R.id.titles);
	<span style="white-space:pre">	</span>mviewPager.setAdapter(detailadapter);		
		//必须在VIewPager设置adapter之后才能调用ViewpagerIndicator
		mIndicator.setViewPager(mviewPager);

    ---设置tab数据

<span style="white-space:pre">	</span>class MenuDetailadapter extends PagerAdapter{
<span style="white-space:pre">		</span>.......

		public CharSequence getPageTitle(int position) {
			// 设置标题在PagerAdapter中
			return newsTabData.get(position).title;
		}
<span style="white-space:pre">	</span>}

     ----设置主题样式

<span style="white-space:pre">	</span><activity
            android:name="com.example.newbj.MainActivity"
            android:theme="@style/Theme.PageIndicatorDefaults" >
        </activity>

    -----修改主题样式

 <span style="white-space:pre">	</span>  <item name="android:background">@drawable/vpi__tab_indicator</item><!-- 背景设置 -->
<span style="white-space:pre">	</span> <item name="android:textColor">@drawable/vpi__tab_text_color_indicator</item><!-- 文字背景-->

④.ViewPagerIndicatorLibrary框架实现位置指示器

----xml布局及样式(使用相对布局和ViewPager叠加)

<span style="white-space:pre">	 xmlns:app="http://schemas.android.com/apk/res-auto"</span>
<span style="white-space:pre">	</span><com.viewpagerindicator.CirclePageIndicator
           <span style="white-space:pre">	</span> android:id="@+id/indicator"
            <span style="white-space:pre">	</span>android:layout_width="wrap_content"
            <span style="white-space:pre">	</span>android:layout_height="wrap_content"
           <span style="white-space:pre">	</span> android:layout_alignParentRight="true"
            <span style="white-space:pre">	</span>android:padding="10dip"
           <span style="white-space:pre">	</span> app:fillColor="#f00"
           <span style="white-space:pre">	</span> app:pageColor="@android:color/darker_gray"
           <span style="white-space:pre">	</span> app:radius="3dp"
          <span style="white-space:pre">	</span>  app:strokeWidth="0dp" />

---代码设置

<span style="white-space:pre">			</span>mViewPager.setAdapter(new TopNewsAdapter());
			// 因为这个和viewpager一起在用,所以让这个设置监听,不然不会改变指示器的移动
			indicator.setOnPageChangeListener(this);

			indicator.setViewPager(mViewPager);
			indicator.setSnap(true);// 支持快照显示
			indicator.onPageSelected(0);// 默认设置为第一个点

二.拦截事件( dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent)

1.大的VIewpager设置不拦截.同时设置不处理touch事件.里面的VIewpager就可以滑动

<span style="white-space:pre">	</span>public boolean onInterceptTouchEvent(MotionEvent arg0) {
			//表示不拦截事件
			return false;
		}

		@Override
		public boolean onTouchEvent(MotionEvent ev) {
			// 表示viewPager什么都不做
			return false;
		}
2.当TabPageIndicator 向左时会被SlideMenu拦截事件 (如果设置SlideMenu的设置不拦截和不处理touch事件的话很复杂)
解决方法:①TabPageIndicator 请求不要拦截  在TabPageIndicator中请求
 当ViewPager向左滑动时也会被SlideMenu拦截事件
解决方法:②ViewPager 请求不要拦截 自定义Viewpager

<span style="white-space:pre">			</span>/**
			 * 事件分发, 请求父控件及祖宗控件不要拦截事件
		 	*/
			@Override
			public boolean dispatchTouchEvent(MotionEvent ev) {
				getParent().requestDisallowInterceptTouchEvent(true);// 用getParent去请求
				return super.dispatchTouchEvent(ev);
			}
3.设置ViewPager北京第一页和 最后一页需要被拦截

<span style="white-space:pre">	</span>/*
	 * 请求上面的viewpager不要拦截这个滑动事件
	 * 
	 * 1.如果是右滑到最后一张图片需要父控件拦截 
	 * 2.如果是左滑到第一种图片需要父控件拦截 
	 * 3.如果是上下滑动需要父控件拦截
	 */
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			startX = ev.getX();
			startY = ev.getY();
			break;
		case MotionEvent.ACTION_MOVE:
			endX = ev.getX();
			endY = ev.getY();

			if (Math.abs(endX - startX) - Math.abs(endY - startY) > 0) {// 左右滑动
				if (endX - startX > 0) {// 向右滑动
					if (getCurrentItem() == 0) {// 是第一张图片
						getParent().requestDisallowInterceptTouchEvent(false);// 拦截
					}else{
						getParent().requestDisallowInterceptTouchEvent(true);// 不拦截
					}
				} else {// 向左滑动
					if (getCurrentItem() == (getAdapter().getCount() - 1)) {// 最后一张图片
						getParent().requestDisallowInterceptTouchEvent(false);// 拦截
					}else{
						getParent().requestDisallowInterceptTouchEvent(true);// 不拦截
					}
				}
			} else {// 上下滑动拦截
				getParent().requestDisallowInterceptTouchEvent(false);
			}

			break;
		case MotionEvent.ACTION_UP:

			break;

		default:
			break;
		}
		
		return super.dispatchTouchEvent(ev);
	}

三.解析json数据(通过Gson解析)

通过HttpUtils获取数据:

<span style="white-space:pre">	</span>HttpUtils httpUtils = new HttpUtils();
		httpUtils.send(HttpMethod.GET, moreUrl, new RequestCallBack<String>() {

			@Override
			public void onSuccess(ResponseInfo<String> responseInfo) {
				String result = (String) responseInfo.result;
				System.out.println("返回数据" + result);
				parseData(result, true);
				listView.OnRefreshComplete(true);
			}

			@Override
			public void onFailure(HttpException error, String msg) {
				Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();
				error.printStackTrace();
				listView.OnRefreshComplete(true);
			}
		});


1.解析数据

<span style="white-space:pre">	</span>Gson gson = new Gson();
		mNewsData = gson.fromJson(result, NewsData.class);
		System.out.println("解析数据" + mNewsData);
2.NewsData类对json实现定义

/*
 * 网络分类信息的封装
 */
public class NewsData {
	//定义的名字必须和服务器返回的名字一致
	public int retcode;
	public ArrayList<NewsMenuData> data;
	//public ArrayList extend;不需要这个
	
	//侧边栏的数据对象
	public class NewsMenuData{
		
		public String id;
		public String title;
		public int type;
		public String url;
		public ArrayList<NewsTabData> children;

		@Override
		public String toString() {
			return "NewsMenuData [title=" + title + ", children=" + children
					+ "]";
		}
	}
	
	//新闻页签下的11个标签对象
	public class NewsTabData{
		public String id;
		public String title;
		public int type;
		public String url;
		@Override
		public String toString() {
			return "NewsTabData [title=" + title + "]";
		}
	}

	@Override
	public String toString() {
		return "NewsData [data=" + data + "]";
	}
}

四.ListView下拉刷新(详情见前面笔记)

1.初始化数据

---3种状态

--下拉刷新状态

--释放刷新状态

--正在刷新状态

	this.addHeaderView(headerView);
		headerView.measure(0, 0);// 通知测量
		measuredHeight = headerView.getMeasuredHeight();
		// 默认将其隐藏
		headerView.setPadding(0, -measuredHeight, 0, 0);

2.设置下拉逻辑(通过判断触摸的事件)

//处理下拉刷新的滑动事件
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			startY = ev.getRawY();
			break;
		case MotionEvent.ACTION_MOVE:
			if (startY == -1) {
				startY = ev.getRawY();
			}
			if (State == STATE_REFRESHING) {
				break;// 如果正在刷新,设置不能下拉。返回
			}
			endY = ev.getRawY();
			float dy = endY - startY;
			// 如果是下拉并且是第一个position才下拉
			if (dy > 0 && getFirstVisiblePosition() == 0) {
				int padding = (int) (dy - measuredHeight);
				headerView.setPadding(0, padding, 0, 0);
				
				// 状态改为释放刷新
				if (padding > 0 && State != STATE_RELEASE_REFRESH) {
					State = STATE_RELEASE_REFRESH;
					StateChange();
					// 状态改为下拉刷新
				} else if (padding < 0 && State != STATE_PULL_REFRESH) {
					State = STATE_PULL_REFRESH;
					StateChange();
				}
				return true;// 避免其他事件处理
			}
			break;
		case MotionEvent.ACTION_UP:
			startY = -1;
			if (State == STATE_RELEASE_REFRESH) {// 如果是释放刷新 变为正在刷新
				State = STATE_REFRESHING;
				headerView.setPadding(0, 0, 0, 0);
				StateChange();
			} else if (State == STATE_PULL_REFRESH) {// 如果是松开
				// State = STATE_RELEASE_REFRESH;
				// 隐藏标题
				headerView.setPadding(0, -measuredHeight, 0, 0);
			}
			break;

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

	//通过状态改变布局显示
	private void StateChange() {
		switch (State) {
		case STATE_PULL_REFRESH:// 下拉状态
			tv_title.setText("下拉刷新");
			iv_arr.setVisibility(View.VISIBLE);
			pb_progress.setVisibility(View.INVISIBLE);
			iv_arr.startAnimation(downanim);
			break;
		case STATE_RELEASE_REFRESH:// 松开状态
			tv_title.setText("松开刷新");
			iv_arr.setVisibility(View.VISIBLE);
			pb_progress.setVisibility(View.INVISIBLE);
			iv_arr.startAnimation(refreshanim);
			break;
		case STATE_REFRESHING:// 正在刷新状态
			tv_title.setText("正在刷新...");
			iv_arr.clearAnimation();// 必须先清除动画才可以设置不可见
			iv_arr.setVisibility(View.INVISIBLE);
			pb_progress.setVisibility(View.VISIBLE);
			
			//当加载完数据回调监听 
			if (onCompleteRefreshListener != null) {
				onCompleteRefreshListener.noShowRefresh();
			}
			break;
		}
	}

3.当加载完数据时调用完成刷新逻辑.隐藏下拉刷新

// 完成刷新之后就将其隐藏的方法
	public void OnRefreshComplete(boolean isLoadMore) {

		if (isLoadMore) {
			// 隐藏脚
			footerView.setPadding(0, -footViewHeight, 0, 0);
		} else {
			State = STATE_PULL_REFRESH;
			tv_title.setText("下拉刷新");
			iv_arr.setVisibility(View.VISIBLE);
			pb_progress.setVisibility(View.INVISIBLE);

			// 刷新完之后就隐藏头
			headerView.setPadding(0, -measuredHeight, 0, 0);
			tv_time.setText("最后刷新:" + getCurrentTime());
		}
	}

五.ListView加载更多

1.初始化数据

<span style="white-space:pre">		</span>this.addFooterView(footerView);
		// 自定义的view获得高需要去先通知测量
		footerView.measure(0, 0);
		footViewHeight = footerView.getMeasuredHeight();
		footerView.setPadding(0, -footViewHeight, 0, 0);
		
2.通过监听滑动的状态设置加载更多

this.setOnScrollListener(this);

/** 加载更多监听 */
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		if (scrollState == SCROLL_STATE_FLING
				|| scrollState == SCROLL_STATE_IDLE) {// 如果是空闲或者是滑动
			if (getLastVisiblePosition() == getCount() - 1) {// 如果是最后一个
				// 显示加载更多
				// footerView.setVisibility(View.VISIBLE);
				footerView.setPadding(0, 0, 0, 0);
				setSelection(getCount() - 1);

				// 设置监听,当加载完数据之后就回调隐藏加载更多
				if (onCompleteRefreshListener != null) {
					onCompleteRefreshListener.noShowLoadMore();
				}
			}
		}

	}

3.完成加载更多之后隐藏加载更多

<span style="white-space:pre">	</span>// 完成刷新之后就将其隐藏的方法
	public void OnRefreshComplete(boolean isLoadMore) {

		if (isLoadMore) {
			// 隐藏脚
			footerView.setPadding(0, -footViewHeight, 0, 0);
		}

六.3级缓存

1.设置缓存类

public class MybitmpaUtils {
	private NetworkCacheUtils networkCacheUtils;
	private SdcardCacheUtils sdcardCacheUtils; 
	private RoomCacheUtils roomCacheUtils;
	public MybitmpaUtils() {
		roomCacheUtils = new RoomCacheUtils();
		sdcardCacheUtils = new SdcardCacheUtils();
		networkCacheUtils = new NetworkCacheUtils(sdcardCacheUtils,roomCacheUtils);
	}
	
	public void display(ImageView ivPic,String url){
		ivPic.setImageResource(R.drawable.news_pic_default);//设置默认图片
		
		
		//1.从内存中读取,最快
		Bitmap bitmapRoom = roomCacheUtils.getDataByRoom(url);
		if(bitmapRoom!=null){
			ivPic.setImageBitmap(bitmapRoom);
			System.out.println("从内存中读取到了");
			return;
		}
		
		//2.从sdcard中读取。第二
		Bitmap bitmap = sdcardCacheUtils.getDatabySdcard(url);
		if(bitmap!=null){
			ivPic.setImageBitmap(bitmap);
			roomCacheUtils.setDatatoRoom(url, bitmap);//保存一份到内存中
			System.out.println("从sdcard中读取到了");
			return;
		}
		
		//3.从网络中读取,第三
		networkCacheUtils.getBitmapFromNet(ivPic, url);
	}

}

2.网络加载使用AsyncTask

//网络读取数据
public class NetworkCacheUtils {
	private HttpURLConnection coon;
	private SdcardCacheUtils sdcardCacheUtils;
	private RoomCacheUtils roomCacheUtils;
	public NetworkCacheUtils(SdcardCacheUtils sdcardCacheUtils, RoomCacheUtils roomCacheUtils) {
		this.sdcardCacheUtils = sdcardCacheUtils;
		this.roomCacheUtils = roomCacheUtils;
	}

	// 根据传入的url给传入的ImageView设置图片
	public void getBitmapFromNet(ImageView ivPic, String url) {
		new BitmapTask().execute(ivPic, url);// 执行异步下载
	}

	public class BitmapTask extends AsyncTask<Object, Void, Bitmap> {

		private ImageView imageView;
		private String url;

		// 执行前调用。初始化数据
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
		}

		//异步下载数据
		@Override
		protected Bitmap doInBackground(Object... params) {
			imageView = (ImageView) params[0];
			url = (String) params[1];
			imageView.setTag(url);
			return downloadBitmap(url);
		}
		
		//
		@Override
		protected void onProgressUpdate(Void... values) {
			super.onProgressUpdate(values);
		}

		//当doInbackground下载完之后会将结果返回到这里(主线程运行)
		@Override
		protected void onPostExecute(Bitmap result) {
			super.onPostExecute(result);
			if (result != null) {
				//获取绑定的Bitmap对象的url
				String bindurl = (String) imageView.getTag();
			
				// 防止图片的重用导致的错乱
				if (url.equals(bindurl)) {
					sdcardCacheUtils.saveDatatoSdcard(result, bindurl);
					roomCacheUtils.setDatatoRoom(bindurl, result);
					imageView.setImageBitmap(result);//设置图片
					System.out.println("从网络拿到图片了。。。。");
				}
			}
		}
	}

	/*
	 * 下载图片的逻辑
	 */
	private Bitmap downloadBitmap(String url) {
		try {
			coon = (HttpURLConnection) new URL(url).openConnection();
			coon.setConnectTimeout(5000);
			coon.setReadTimeout(5000);
			coon.setRequestMethod("GET");
			coon.connect();

			int responseCode = coon.getResponseCode();
			if (responseCode == 200) {
				InputStream inputStream = coon.getInputStream();
				
				//对图片进行压缩
				BitmapFactory.Options options = new BitmapFactory.Options();
				options.inSampleSize = 2 ;//宽高缩小为原来的2分之一
				options.inPreferredConfig = Bitmap.Config.RGB_565;
				Bitmap bitmap = BitmapFactory.decodeStream(inputStream,null,options);
				return bitmap;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			coon.disconnect();
		}
		return null;
	}
}

3.Sdcard缓存

public class SdcardCacheUtils {
	private static final String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/nzhbj";

	public void saveDatatoSdcard(Bitmap bitmap, String url) {
		
			String fileName;
			try {
				fileName = MD5Encoder.encode(url);//根据图片的url设置名字
				File file = new File(path, fileName);//创建File对象 
				//如果没有父文件夹。则创建
				File parentFile = file.getParentFile();
				if (!parentFile.exists()) {
					parentFile.mkdirs();
				}
				FileOutputStream fileOutputStream = new FileOutputStream(file);
				//保存图片到流中	jpeg格式 100是不压缩
				bitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
			} catch (Exception e1) {
				e1.printStackTrace();
			}
	}
	//从Sdcard中获取bitmap对象
	public Bitmap getDatabySdcard(String url){
		try {
			String fileName = MD5Encoder.encode(url);
			File file = new File(path,fileName);
			if(file.exists()){
				Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
				return bitmap;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

4.内存缓存

public class RoomCacheUtils {
	
	//一般对象:HashMap<String, Bitmap> hashMap = new HashMap<String, Bitmap>();
	//软引用对象:HashMap<String, SoftReference<Bitmap>>hashMap = new HashMap<String, SoftReference<Bitmap>>();
	//SoftReference<Bitmap> reference = hashMap.get(url);
	private LruCache<String, Bitmap>lruCache; //使用最少最近算法
	public  RoomCacheUtils(){
		//设置lruCache缓存的大小一半为总内存的8分之一
		float maxSize = Runtime.getRuntime().maxMemory()/8;//模拟器默认是16m
		lruCache = new LruCache<String, Bitmap>((int)maxSize){
			@Override
			protected int sizeOf(String key, Bitmap value) {
				//返回一张图片的大小 
				int rowBytes = value.getByteCount();
				return rowBytes;
			}
		};
			
	}
	//保存对象在内存中
	public void setDatatoRoom(String url , Bitmap bitmap ){
		lruCache.put(url, bitmap);
	}
	//从内存中读取Bitmap对象
	public Bitmap getDataByRoom(String url){
		
		Bitmap bitmap = lruCache.get(url);
		return bitmap;
	}
}

5.内存缓存避免oom

----使用LRU算法加载bitmap对象

----压缩图片

	<span style="white-space:pre">	</span>//对图片进行压缩
				BitmapFactory.Options options = new BitmapFactory.Options();
				options.inSampleSize = 2 ;//宽高缩小为原来的2分之一
				options.inPreferredConfig = Bitmap.Config.RGB_565;
				Bitmap bitmap = BitmapFactory.decodeStream(inputStream,null,options);
				return bitmap;

七.屏幕适配(见第6天)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值