編輯:關於Android編程
此頁面相對比較復雜,所以單獨用一篇blog來說明都處理了哪些邏輯
private void getDataFromNet() {
HttpUtils httpUtils = new HttpUtils();
httpUtils.send(HttpRequest.HttpMethod.GET, url, new RequestCallBack
解析json(javaBean在此不做贅述,獲取json,直接生成即可)解析json數據分為若干部分,解析json、初始化數據、設置數據、處理和解析數據。
private TopNewsBean topNewsJson(String result) {
Gson gson = new Gson();
TopNewsBean topNewsBean;
topNewsBean = gson.fromJson(result, TopNewsBean.class);
return topNewsBean;
}
初始化數據、設置數據
/**
* 解析json數據
*
* @param result
*/
private void resolutionJson(String result) {
TopNewsBean topNewsBean = topNewsJson(result);
if (!isLoadMore){
//把解析json封裝成一個方法這樣看起來代碼沒那麼亂
topNewsList = topNewsBean.getData().getTopnews();
moreUrl = topNewsBean.getData().getMore();
if (TextUtils.isEmpty(moreUrl)) {
moreUrl = null;
}else {
moreUrl = ConstantUtils.CONNECTURL+moreUrl;
}
//初始化頂部新聞的Viewpager數據
//初始化Viewpager數據
TopNewsTabAdapter topNewsTabAdapter = new TopNewsTabAdapter();
// 給ViewPager設置數據
hvp.setAdapter(topNewsTabAdapter);
hvp.setOnPageChangeListener(this);
//初始化文字和點
llPoint.removeAllViews();//因為訪問網絡讀取緩存這個方法會被執行2此,所以需要要移除以前的view
View view = null;
for (int i = 0; i < topNewsList.size(); i++) {
view = new View(mActivity);
view.setBackgroundResource(R.drawable.point_seclect);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(15, 15);
if (i != 0) {
params.leftMargin = 15;
}
view.setEnabled(false);
view.setLayoutParams(params);
llPoint.addView(view);
}
//初始化第一個點和文字
firstDescription = 0;
tvTopNewsDes.setText(topNewsList.get(firstDescription).getTitle());
llPoint.getChildAt(firstDescription).setEnabled(true);
//初始化listview數據
newsItem = topNewsBean.getData().getNews();
listNewsAdapter = new ListNewsAdapter();
listNews.setAdapter(listNewsAdapter);
// TODO: 16/5/28 給Viewpager設置自動滑動
//因為該方法會執行2次,所以需要清空一次
if (myHandle==null){
myHandle = new MyHandle();
}else {
myHandle.removeCallbacksAndMessages(null);
}
myHandle.postDelayed(new MyRunnable(),4000);
}else {
isLoadMore = false;
List moreNewsItem = topNewsBean.getData().getNews();
newsItem.addAll(moreNewsItem);
listNewsAdapter.notifyDataSetChanged();
}
}
處理和解析數據
1、輪播圖數據
class TopNewsTabAdapter extends PagerAdapter {
@Override
public int getCount() {
return topNewsList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(mActivity);
//給imageview設置事件
//設置默認圖片和背景拉伸
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setBackgroundResource(R.drawable.default_bg);
bitmapUtils = new BitmapUtils(mActivity);
// 配置默認圖片的像素單位
bitmapUtils.configDefaultBitmapConfig(Bitmap.Config.ARGB_4444);
//topimage的網絡地址
topNews = topNewsList.get(position);
/**
* container 下面的uri參數請求下來的圖片, 設置給container來展示.
* uri 圖片的請求地址
*/
bitmapUtils.display(imageView, topNews.getTopimage());
container.addView(imageView);
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
2、列表listview新聞數據
class ListNewsAdapter extends BaseAdapter {
@Override
public int getCount() {
return newsItem.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = View.inflate(mActivity, R.layout.listnews_item, null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
TopNewsBean.DataBean.NewsBean newsBean = newsItem.get(position);
viewHolder.tvListNews.setText(newsBean.getTitle());
viewHolder.tvListDate.setText(newsBean.getPubdate());
// 判斷當前是否是已讀的新聞
String readableIDArray = CacheUtils.getString(mActivity, READABLE_NEWS_ID_ARRAY_KEY, null);
// TODO: 16/5/27
if(!TextUtils.isEmpty(readableIDArray)
&& readableIDArray.contains(newsBean.getId()+"")) {
viewHolder.tvListNews.setTextColor(Color.GRAY);
} else {
viewHolder.tvListNews.setTextColor(Color.BLACK);
}
//設置默認圖片
viewHolder.ivListNews.setBackgroundResource(R.drawable.listnews_default_bg);
bitmapUtils.display(viewHolder.ivListNews,newsBean.getListimage());
return convertView;
}
class ViewHolder {
@Bind(R.id.iv_list_news)
public ImageView ivListNews;
@Bind(R.id.tv_list_news)
public TextView tvListNews;
@Bind(R.id.tv_list_date)
public TextView tvListDate;
ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
}
設置點和文字的自動切換、自動輪播
設置點和文字的自動切換
1、給Viewpager設置頁面滑動監聽
2、初始化點和文字描述控件
//初始化文字和點
llPoint.removeAllViews();//因為訪問網絡讀取緩存這個方法會被執行2此,所以需要要移除以前的view
View view = null;
for (int i = 0; i < topNewsList.size(); i++) {
view = new View(mActivity);
view.setBackgroundResource(R.drawable.point_seclect);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(15, 15);
if (i != 0) {
params.leftMargin = 15;
}
view.setEnabled(false);
view.setLayoutParams(params);
llPoint.addView(view);
}
//初始化第一個點和文字
firstDescription = 0;
tvTopNewsDes.setText(topNewsList.get(firstDescription).getTitle());
llPoint.getChildAt(firstDescription).setEnabled(true);
3、主要實現onPageSelected方法
//Viewpager的滑動事件監聽
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
//設置點的切換
tvTopNewsDes.setText(topNewsList.get(position).getTitle());
llPoint.getChildAt(firstDescription).setEnabled(false);
llPoint.getChildAt(position).setEnabled(true);
firstDescription = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
自動輪播(通過Handle實現,定時任務)
為什麼執行2次,第一次從緩存中讀取數據,並處理數據,第二次從網絡上獲取數據,並處理數據。
// TODO: 16/5/28 給Viewpager設置自動滑動
//因為該方法會執行2次,所以需要清空一次
if (myHandle==null){
myHandle = new MyHandle();
}else {
myHandle.removeCallbacksAndMessages(null);
}
myHandle.postDelayed(new MyRunnable(),4000);
}else {
isLoadMore = false;
List moreNewsItem = topNewsBean.getData().getNews();
newsItem.addAll(moreNewsItem);
listNewsAdapter.notifyDataSetChanged();
}
//Handle
class MyHandle extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//用於處理消息
int newCurrentItem = (hvp.getCurrentItem() + 1)%topNewsList.size();
hvp.setCurrentItem(newCurrentItem);
//消息處理完在重新發送,類似遞歸
myHandle.postDelayed(new MyRunnable(),4000);
}
}
//run方法
class MyRunnable implements Runnable{
@Override
public void run() {
//發一條空的消息
myHandle.sendEmptyMessage(0);
}
}
下拉刷新、上拉加載
寫一個類繼承自listview,添加自定義頭布局和尾布局,監聽滑動事件等。
以下貼出關鍵代碼。
下拉刷新部分
添加頭布局
/**
* 添加頭布局
*/
private void initHeadView() {
headView = View.inflate(getContext(), R.layout.refresh_headview, null);
ButterKnife.bind(this, headView);
this.addHeaderView(headView);
//默認隱藏頭布局
headView.measure(0, 0);
measuredHeight = headView.getMeasuredHeight();
headView.setPadding(0, -measuredHeight, 0, 0);
initAnimation();
}
處理Listview的點擊事件
/**
* 重新onTouchEvent,處理點擊事件
* @param ev
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (downY == -1){
downY = (int) ev.getY();
}
// downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (downY == -1){
downY = (int) ev.getY();
}
int moveY = (int) ev.getY();
int diffY = moveY - downY;
// 判斷當前是否正在刷新中
if(currentState == RELEASEREFRESH) {
// 當前正在刷新中, 不執行下拉, 直接跳出
break;
}
//如果是從上向下滑動,並且是第一個頭布局,才進行下拉操作
boolean isDisplay = isDisplaySecondHeaderView();
if (diffY>0&&isDisplay) {
int piddingTop = -measuredHeight+diffY;
if (piddingTop >= 0 && currentState != RELEASEREFRESH){
Log.i(TAG, "進入釋放刷新狀態");
currentState = RELEASEREFRESH;
refreshState();
}else if (piddingTop<0 && currentState != DOWNREFRESH){
Log.i(TAG, "進入下拉刷新");
currentState = DOWNREFRESH;
refreshState();
}
headView.setPadding(0,piddingTop,0,0);
return true;
}
break;
case MotionEvent.ACTION_UP:
downY = -1;
if(currentState == DOWNREFRESH) {
// 當前是下拉刷新, 把頭布局的隱藏
headView.setPadding(0, -measuredHeight, 0, 0);
} else if(currentState == RELEASEREFRESH) {
// 當前是釋放刷新, 進入到正在刷新中的狀態
currentState = INREFRESH;
refreshState();
headView.setPadding(0, 0, 0, 0);
// 調用用戶的回調事件, 刷新數據
if(mOnRefreshListener != null) {
mOnRefreshListener.onPullDownRefresh();
}
}
break;
}
return super.onTouchEvent(ev);
//判斷3種狀態
private void refreshState() {
switch (currentState) {
case DOWNREFRESH: //下拉刷新
ivRefresh.startAnimation(downAnima);
tvRefresh.setText("下拉刷新");
break;
case RELEASEREFRESH: //釋放刷新
ivRefresh.startAnimation(upAnima);
tvRefresh.setText("松開刷新");
break;
case INREFRESH: //刷新中
ivRefresh.clearAnimation();
ivRefresh.setVisibility(View.INVISIBLE);
pbBar.setVisibility(View.VISIBLE);
tvRefresh.setText("正在刷新中..");
break;
}
}
定義回調接口
public interface OnRefreshListener {
/**
* 當下拉刷新時觸發此方法
*/
public void onPullDownRefresh();
public void onLoadingMore();
}
上拉加載更多部分
/**
* 添加角布局
*/
private void initFooterView() {
footView = View.inflate(getContext(), R.layout.listview_footerview, null);
footView.measure(0,0);
footViewHeight = footView.getMeasuredHeight();
this.addFooterView(footView);
footView.setPadding(0, -footViewHeight, 0, 0);
this.setOnScrollListener(new OnScrollListener() {
//當頁面改變是調用
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 當滾動停止時, 或者慣性滑動時, ListView最後一個顯示的條目索引為getCount -1;
if(scrollState == SCROLL_STATE_IDLE ||
scrollState == SCROLL_STATE_FLING) {
if(getLastVisiblePosition() == getCount() -1 && !isLoadingMore) {
System.out.println("滾動到底部了");
isLoadingMore = true;
footView.setPadding(0, 0, 0, 0);
// 讓ListView滾動到底部
setSelection(getCount());
// 調用使用者的回調事件
if(mOnRefreshListener != null) {
mOnRefreshListener.onLoadingMore();
}
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
}
點擊listview條目進入一個新的頁面,通過WebView展示一個web網頁
listNews.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
int newsposition = position - 2;
newsBeanItem = newsItem.get(newsposition);
// 先把已讀新聞的id取出來
String readableIDArray = CacheUtils.getString(mActivity, READABLE_NEWS_ID_ARRAY_KEY, "");
if(!readableIDArray.contains(newsBeanItem.getId()+"")) {
String currentID = null;
if(TextUtils.isEmpty(readableIDArray)) {
currentID = newsBeanItem.getId() + ", ";
} else {
currentID = readableIDArray + newsBeanItem.getId() + ", ";
}
// 把這條新聞的id存儲起來
CacheUtils.putString(mActivity, READABLE_NEWS_ID_ARRAY_KEY, currentID);
}
listNewsAdapter.notifyDataSetChanged();
Intent intent = new Intent(mActivity, NewsDetailUI.class);
intent.putExtra("url", newsBeanItem.getUrl());
intent.putExtra("title",newsBeanItem.getTitle());
mActivity.startActivity(intent);
}
});
初始化數據
private void initData() {
mIbFinish.setVisibility(View.VISIBLE);
mIbTextSize.setVisibility(View.VISIBLE);
mIbShare.setVisibility(View.VISIBLE);
mTvTitle.setMaxWidth(600);
mTvTitle.setMaxLines(1);
mTvTitle.setEllipsize(TextUtils.TruncateAt.valueOf("END"));
mTvTitle.setText(getIntent().getStringExtra("title"));
String url = getIntent().getStringExtra("url");
settings = mWebView.getSettings();
// settings.setJavaScriptEnabled(true); // 啟用javascript腳本
// settings.setBuiltInZoomControls(true); // 啟用界面上放大和縮小按鈕
// settings.setUseWideViewPort(true); // 啟用雙擊放大, 雙擊縮小功能
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
mPbLoading.setVisibility(View.GONE);
}
});
mWebView.loadUrl(url);
}
設置字體大小
/**
* 設置webView的字體大小
*/
private void setTextSize() {
AlertDialog.Builder ab = new AlertDialog.Builder(this);
ab.setTitle("選擇字體大小");
String[] item = new String[]{"超大號字體","大號字體","正常字體","小號字體","超小號字體"};
ab.setSingleChoiceItems(item, currentSelectTextSize, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
tempCurrent = which;
}
});
ab.setNeutralButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
currentSelectTextSize = tempCurrent;
changeTextSize();
}
});
ab.setPositiveButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
ab.show();
}
share分享(第三方sdk使用在這裡暫時不做介紹,根據官方文檔一步一步就行了)
/**
* 一鍵社會化分享
*/
private void mobShare() {
ShareSDK.initSDK(this);
OnekeyShare oks = new OnekeyShare();
//關閉sso授權
oks.disableSSOWhenAuthorize();
// 分享時Notification的圖標和文字 2.5.9以後的版本不調用此方法
//oks.setNotification(R.drawable.ic_launcher, getString(R.string.app_name));
// title標題,印象筆記、郵箱、信息、微信、人人網和QQ空間使用
oks.setTitle("智慧北京");
// titleUrl是標題的網絡鏈接,僅在人人網和QQ空間使用
oks.setTitleUrl("http://sharesdk.cn");
// text是分享文本,所有平台都需要這個字段
oks.setText("我是分享文本");
// imagePath是圖片的本地路徑,Linked-In以外的平台都支持此參數
//oks.setImagePath("/sdcard/test.jpg");//確保SDcard下面存在此張圖片
// url僅在微信(包括好友和朋友圈)中使用
oks.setUrl("http://sharesdk.cn");
// comment是我對這條分享的評論,僅在人人網和QQ空間使用
oks.setComment("我是測試評論文本");
// site是分享此內容的網站名稱,僅在QQ空間使用
oks.setSite(getString(R.string.app_name));
// siteUrl是分享此內容的網站地址,僅在QQ空間使用
oks.setSiteUrl("http://sharesdk.cn");
// 啟動分享GUI
oks.show(this);
}
簡單幾步,獲取數據,解析數據
初始化數據
@Override
public void initData() {
bitmapUtils = new BitmapUtils(mActivity);
bitmapUtils.configDefaultBitmapConfig(Bitmap.Config.ARGB_4444);
url = ConstantUtils.PHOTOSURL;
//先從緩存中讀取數據
String photosJsonData = CacheUtils.getString(mActivity, url, null);
if (photosJsonData != null) {
parserJsonData(photosJsonData);
}
//從網絡上請求數據
getDataFromNet();
}
private void getDataFromNet() {
HttpUtils httpUtils = new HttpUtils();
httpUtils.send(HttpRequest.HttpMethod.GET, url, new RequestCallBack
解析數據
private void parserJsonData(String result) {
PhotosBean photosBean = parserJson(result);
//主要取得數據圖片的url+title
photoNews = photosBean.getData().getNews();
//設置listview數據
PhotoAdapter photoAdapter = new PhotoAdapter();
llPhotos.setAdapter(photoAdapter);
}
private PhotosBean parserJson(String result) {
Gson gson = new Gson();
PhotosBean photosBean = gson.fromJson(result, PhotosBean.class);
return photosBean;
}
class PhotoAdapter extends BaseAdapter {
@Override
public int getCount() {
return photoNews.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = View.inflate(mActivity, R.layout.photos_list_item, null);
viewHolder.ivPhotoPhotos = (ImageView) convertView.findViewById(R.id.iv_photo_photos);
viewHolder.tvTitlePhotos = (TextView) convertView.findViewById(R.id.tv_title_photos);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
PhotosBean.DataBean.NewsBean newsBean = photoNews.get(position);
viewHolder.tvTitlePhotos.setText(newsBean.getTitle());
//設置默認圖片
viewHolder.ivPhotoPhotos.setImageResource(R.drawable.default_bg);
bitmapUtils.display(viewHolder.ivPhotoPhotos,newsBean.getListimage());
return convertView;
}
public class ViewHolder {
// @Bind(R.id.iv_photo_photos)
public ImageView ivPhotoPhotos;
// @Bind(R.id.tv_title_photos)
public TextView tvTitlePhotos;
}
}
切換視圖
/**
* 用於切換視圖的方法
* @param ib
*/
public void switchView(ImageButton ib) {
//more沒有切換是listv
if (isSingleColumns) {
llPhotos.setVisibility(View.VISIBLE);
gvPhoto.setVisibility(View.GONE);
llPhotos.setAdapter(new PhotoAdapter());
isSingleColumns =false;
ib.setImageResource(R.mipmap.icon_pic_list_type);
}else {
llPhotos.setVisibility(View.GONE);
gvPhoto.setVisibility(View.VISIBLE);
gvPhoto.setAdapter(new PhotoAdapter());
isSingleColumns =true;
ib.setImageResource(R.mipmap.icon_pic_grid_type);
}
}
至此,本小項目完成。其他頁面暫不做實現,其處理邏輯參考“新聞中心”頁面即可。
前面簡單介紹了下GreenDao的使用,從前面的介紹看來是不是覺得有點 so easy。對就是這麼簡單。曾經有位大神說作為一位合格的程序員就要在學習別人的東西時,有點自己
序言這篇博文不是對事件分發機制全面的介紹,只是從源碼的角度分析ACTION_DOWN、ACTION_MOVE、ACTION_UP事件在ViewGroup中的分發邏輯,了解
RecyclerView已經出來很久了,許許多多的項目都開始從ListView轉戰RecyclerView,那麼,上拉加載和下拉刷新是一件很有必要的事情。在ListVie
騰訊開放平台的接入是非常麻煩的, open.qq.com,騰訊開放平台的文檔很多很雜,社交功能的api接口也很多還有。我現在只接了他的登錄跟支付。 一、登錄。 登錄相對來
Android 高德地圖 java.lang.Unsatisfiedli