Android学习笔记_48_若水新闻客户端源码剖析

时间:2021-05-28 00:23:00

一、新闻客户端布局代码

1.1 主界面布局

    使用GridView实现左右可滑动菜单项,使用标签HorizontalScrollView实现水平滚动条,将创建的GridView添加到布局文件中。 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@id/main_layout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/main_background"
>
<RelativeLayout
android:id="@id/titlebar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/titlebar_background"
>
<TextView
android:id="@id/titlebar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8.0dip"
android:layout_marginLeft="15.0dip"
android:textAppearance="@style/titlebar_title_style"
android:text="@string/app_name"/>
<Button
android:id="@id/titlebar_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/titlebar_btn_refresh_selector"
android:layout_marginTop="7.0dip"
android:layout_marginRight="14.0dip"
android:layout_alignParentRight="true"
/>
<ProgressBar
android:id="@id/loadnews_progress"
android:layout_width="25.0dip"
android:layout_height="25.0dip"
android:clickable="false"
android:visibility="gone"
android:layout_marginRight="20.0dip"
android:layout_marginTop="10.0dip"
android:layout_alignParentRight="true"
style="?android:attr/progressBarStyleLarge" />
</RelativeLayout>
<RelativeLayout
android:id="@id/categorybar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/categorybar_background"
android:layout_marginTop="-18.0dip"
>
<Button
android:id="@id/category_arrow_right"
android:layout_width="6.0dip"
android:layout_height="10.0dip"
android:background="@drawable/categorybar_right_arrow"
android:layout_marginLeft="2.0dip"
android:layout_marginRight="10.0dip"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
<HorizontalScrollView
android:id="@id/category_scrollview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6.0dip"
android:scrollbars="none"
android:layout_toLeftOf="@id/category_arrow_right"
android:layout_centerVertical="true">
<LinearLayout
android:id="@id/category_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
/>
</HorizontalScrollView>
</RelativeLayout>
<ListView
android:id="@+id/newslist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:listSelector="@drawable/newslist_item_selector"
android:cacheColorHint="#00000000"
android:divider="@drawable/list_separator_line"
/>
</LinearLayout>

二、ViewFlipper的应用

2.1 界面布局

    进入到新闻详细界面,通过手指滑动实现下一条新闻和上一条新闻的切换。newsdetails.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@id/newsdetails_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/main_background"
android:layout_marginBottom="0.0dip"
>
<RelativeLayout
android:id="@id/newsdetails_titlebar_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/titlebar_background"
>
<Button
android:id="@id/newsdetails_titlebar_previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7.0dip"
android:layout_marginLeft="5.0dip"
android:layout_alignParentLeft="true"
android:background="@drawable/newsdetails_title_previous_btn_selector"
android:textSize="14.0sp"
android:textStyle="bold"
/>
<TextView
android:id="@id/newsdetails_titlebar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15.0dip"
android:layout_marginTop="10.0dip"
android:layout_toRightOf="@id/newsdetails_titlebar_previous"
android:textSize="18.0sp"
android:textColor="@color/white"
android:text="国内"
/>
<Button
android:id="@id/newsdetails_titlebar_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7.0dip"
android:layout_marginRight="5.0dip"
android:layout_alignParentRight="true"
android:background="@drawable/newsdetails_title_next_btn_selector"
/>
<Button
android:id="@id/newsdetails_titlebar_comments"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="60.0dip"
android:layout_marginTop="9.0dip"
android:background="@drawable/newsdetails_titlebar_comments_background"
android:textColor="@color/white"
android:text="0跟帖"
/>
<ProgressBar
android:id="@id/loadnews_progress"
android:layout_width="25.0dip"
android:layout_height="25.0dip"
android:clickable="false"
android:visibility="gone"
android:layout_marginRight="30.0dip"
android:layout_marginTop="10.0dip"
android:layout_alignParentRight="true"
style="?android:attr/progressBarStyleLarge" />
</RelativeLayout> <ViewFlipper
android:id="@id/news_body_flipper"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/main_background"
android:layout_marginTop="-12.0dip"
android:layout_marginBottom="40.0dip"
android:layout_below="@id/newsdetails_titlebar_layout" /> <include
android:id="@id/comments_reply_frame"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
layout="@layout/reply_frame" />
</RelativeLayout>

news_body.xml

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:szy="http://schemas.android.com/apk/res/com.szy.news.activity"
android:id="@id/news_body_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/newsdetails_titlebar_layout"
>
<ScrollView
android:id="@id/news_body_scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFE7E7E7"
android:fadingEdge="none"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@id/news_body_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="12.0dip"
android:layout_marginTop="12.0dip"
android:layout_marginRight="12.0dip"
android:textColor="#FF272727"
android:textSize="18.0dip"
android:textStyle="bold"
/>
<TextView
android:id="@id/news_body_ptime_source"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="12.0dip"
android:layout_marginTop="9.0dip"
android:layout_marginRight="12.0dip"
android:textColor="#FF888888"
android:textSize="12.0sp"
/>
<ImageView
android:id="@id/news_body_separator_line"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8.0dip"
android:visibility="visible"
android:src="@drawable/list_separator_line"
/>
<ProgressBar
android:id="@id/news_body_details_loading"
android:layout_width="16.0dip"
android:layout_height="16.0dip"
android:layout_marginLeft="152.0dip"
android:layout_marginTop="10.0dip"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="gone"
android:clickable="false"
style="?android:attr/progressBarStyleLarge" />
</LinearLayout>
<!--
<TextView
android:id="@id/news_body_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5.0dip"
android:textColor="#ff000000"
/>
-->
<com.szy.news.view.CustomTextView
android:id="@id/news_body_details"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
szy:image_width="200dip"
szy:image_height="52dip"
/>
</LinearLayout>
</ScrollView>
</LinearLayout>

详细新闻的activity的实现,通过自定义控件显示新闻内容,监听新闻内容的触摸事件:

package com.szy.news.activity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import org.json.JSONArray;
import org.json.JSONObject; import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper; import com.szy.news.model.Parameter;
import com.szy.news.service.SyncHttp;
import com.szy.news.view.CustomTextView; /**
*@author coolszy
*@date 2012-3-19
*@blog http://blog.92coding.com
*/
public class NewsDetailsActivity extends Activity
{
private final int FINISH = 0; private ViewFlipper mNewsBodyFlipper;
private LayoutInflater mNewsBodyInflater;
private float mStartX;
private ArrayList<HashMap<String, Object>> mNewsData;
private int mPosition = 0;
private int mCursor;
private int mNid;
private CustomTextView mNewsDetails;
private Button mNewsdetailsTitlebarComm;// 新闻回复数
private ImageButton mNewsReplyImgBtn;// 发表新闻回复图片
private LinearLayout mNewsReplyImgLayout;// 发表新闻回复图片Layout
private LinearLayout mNewsReplyEditLayout;// 发表新闻回复回复Layout
private TextView mNewsReplyContent;// 新闻回复内容
private boolean keyboardShow = false; //软件盘是否可见 private Handler mHandler = new Handler()
{
@SuppressWarnings("unchecked")
@Override
public void handleMessage(Message msg)
{
switch (msg.arg1)
{
case FINISH:
// 把获取到的新闻显示到界面上
ArrayList<HashMap<String, Object>> bodyList = (ArrayList<HashMap<String,Object>>)msg.obj;
System.out.println("###:"+bodyList.size());
mNewsDetails.setText(bodyList);
break;
}
}
}; @SuppressWarnings("unchecked")
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.newsdetails); // 查找新闻回复图片Layout
mNewsReplyImgLayout = (LinearLayout) findViewById(R.id.news_reply_img_layout);
// 查找新闻回复回复Layout
mNewsReplyEditLayout = (LinearLayout) findViewById(R.id.news_reply_edit_layout);
// 新闻回复内容
mNewsReplyContent = (TextView) findViewById(R.id.news_reply_edittext); NewsDetailsOnClickListener newsDetailsOnClickListener = new NewsDetailsOnClickListener();
// 上一篇新闻
Button newsDetailsTitlebarPref = (Button) findViewById(R.id.newsdetails_titlebar_previous);
newsDetailsTitlebarPref.setOnClickListener(newsDetailsOnClickListener);
// 下一篇新闻
Button newsDetailsTitlebarNext = (Button) findViewById(R.id.newsdetails_titlebar_next);
newsDetailsTitlebarNext.setOnClickListener(newsDetailsOnClickListener);
// 新闻回复条数Button
mNewsdetailsTitlebarComm = (Button) findViewById(R.id.newsdetails_titlebar_comments);
mNewsdetailsTitlebarComm.setOnClickListener(newsDetailsOnClickListener);
// 发表新闻回复图片Button
mNewsReplyImgBtn = (ImageButton) findViewById(R.id.news_reply_img_btn);
mNewsReplyImgBtn.setOnClickListener(newsDetailsOnClickListener);
// 发表回复
Button newsReplyPost = (Button) findViewById(R.id.news_reply_post);
newsReplyPost.setOnClickListener(newsDetailsOnClickListener); // 获取传递的数据
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
// 设置标题栏名称
String categoryName = bundle.getString("categoryName");
TextView titleBarTitle = (TextView) findViewById(R.id.newsdetails_titlebar_title);
titleBarTitle.setText(categoryName);
// 获取新闻集合
Serializable s = bundle.getSerializable("newsDate");
mNewsData = (ArrayList<HashMap<String, Object>>) s;
// 获取点击位置
mCursor = mPosition = bundle.getInt("position"); // 动态创建新闻视图,并赋值
mNewsBodyInflater = getLayoutInflater();
inflateView(0);
} /**
* 处理NewsDetailsTitleBar点击事件
*/
class NewsDetailsOnClickListener implements OnClickListener
{
@Override
public void onClick(View v)
{
InputMethodManager m = (InputMethodManager) mNewsReplyContent.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
switch (v.getId())
{
// 上一条新闻
case R.id.newsdetails_titlebar_previous:
showPrevious();
break;
// 下一条新闻
case R.id.newsdetails_titlebar_next:
showNext();
break;
// 显示评论
case R.id.newsdetails_titlebar_comments:
Intent intent = new Intent(NewsDetailsActivity.this, CommentsActivity.class);
//传递新闻ID
intent.putExtra("nid", mNid);
startActivity(intent);
break;
// 新闻回复图片
case R.id.news_reply_img_btn:
mNewsReplyImgLayout.setVisibility(View.GONE);
mNewsReplyEditLayout.setVisibility(View.VISIBLE);
mNewsReplyContent.requestFocus();
m.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT);
keyboardShow = true;
break;
// 发表新闻回复
case R.id.news_reply_post:
mNewsReplyEditLayout.post(new PostCommentThread());
mNewsReplyImgLayout.setVisibility(View.VISIBLE);
mNewsReplyEditLayout.setVisibility(View.GONE);
m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
break;
}
}
} /**
* 处理新闻NewsBody触摸事件
*/
class NewsBodyOnTouchListener implements OnTouchListener
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getAction())
{
// 手指按下
case MotionEvent.ACTION_DOWN:
if (keyboardShow)
{
// 设置新闻回复Layout是否可见
mNewsReplyImgLayout.setVisibility(View.VISIBLE);
mNewsReplyEditLayout.setVisibility(View.GONE);
InputMethodManager m = (InputMethodManager) mNewsReplyContent.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
keyboardShow = false;
}
// 记录起始坐标
mStartX = event.getX();
break;
// 手指抬起
case MotionEvent.ACTION_UP:
// 往左滑动
if (event.getX() < mStartX)
{
showPrevious();
}
// 往右滑动
else if (event.getX() > mStartX)
{
showNext();
}
break;
}
return true;
}
} /**
* 显示下一条新闻
*/
private void showNext()
{
// 判断是否是最后一篇win问:mPosition: 当前新闻的索引
if (mPosition < mNewsData.size() - 1)
{
// 设置下一屏动画
mNewsBodyFlipper.setInAnimation(this, R.anim.push_left_in);
mNewsBodyFlipper.setOutAnimation(this, R.anim.push_left_out);
mPosition++;
HashMap<String, Object> hashMap = mNewsData.get(mPosition);
mNid = (Integer) hashMap.get("nid");
// 判断下一屏是否已经创建
if (mPosition >= mNewsBodyFlipper.getChildCount())
{
inflateView(mNewsBodyFlipper.getChildCount());
}
// 显示下一屏
mNewsBodyFlipper.showNext();
} else
{
Toast.makeText(this, R.string.no_next_news, Toast.LENGTH_SHORT).show();
}
System.out.println(mCursor + ";" + mPosition);
} private void showPrevious()
{
if (mPosition > 0)
{
mPosition--;
// 记录当前新闻编号
HashMap<String, Object> hashMap = mNewsData.get(mPosition);
mNid = (Integer) hashMap.get("nid");
if (mCursor > mPosition)
{
mCursor = mPosition;
inflateView(0);
System.out.println(mNewsBodyFlipper.getChildCount());
mNewsBodyFlipper.showNext();// 显示下一页
}
mNewsBodyFlipper.setInAnimation(this, R.anim.push_right_in);// 定义下一页进来时的动画
mNewsBodyFlipper.setOutAnimation(this, R.anim.push_right_out);// 定义当前页出去的动画
mNewsBodyFlipper.showPrevious();// 显示上一页
} else
{
Toast.makeText(this, R.string.no_pre_news, Toast.LENGTH_SHORT).show();
}
} private void inflateView(int index)
{
// 动态创建新闻视图,并赋值
View newsBodyLayout = mNewsBodyInflater.inflate(R.layout.news_body, null);
// 获取点击新闻基本信息
HashMap<String, Object> hashMap = mNewsData.get(mPosition);
// 新闻标题
TextView newsTitle = (TextView) newsBodyLayout.findViewById(R.id.news_body_title);
newsTitle.setText(hashMap.get("newslist_item_title").toString());
// 发布时间和出处
TextView newsPtimeAndSource = (TextView) newsBodyLayout.findViewById(R.id.news_body_ptime_source);
newsPtimeAndSource.setText(hashMap.get("newslist_item_ptime").toString() + " " + hashMap.get("newslist_item_source").toString());
// 新闻编号
mNid = (Integer) hashMap.get("nid");
// 新闻回复数
mNewsdetailsTitlebarComm.setText(hashMap.get("newslist_item_comments") + "跟帖"); // 把新闻视图添加到Flipper中
mNewsBodyFlipper = (ViewFlipper) findViewById(R.id.news_body_flipper);
mNewsBodyFlipper.addView(newsBodyLayout, index); // 给新闻Body添加触摸事件
mNewsDetails = (CustomTextView) newsBodyLayout.findViewById(R.id.news_body_details);
mNewsDetails.setOnTouchListener(new NewsBodyOnTouchListener()); // 启动线程
new UpdateNewsThread().start();
} /**
* 获取新闻详细信息
*
* @return
*/
private ArrayList<HashMap<String, Object>> getNewsBody()
{
// String retStr = "网络连接失败,请稍后再试";
ArrayList<HashMap<String, Object>> bodyList = new ArrayList<HashMap<String,Object>>();
SyncHttp syncHttp = new SyncHttp();
String url = "http://10.0.2.2:8080/web/getNews";
String params = "nid=" + mNid;
try
{
String retString = syncHttp.httpGet(url, params);
JSONObject jsonObject = new JSONObject(retString);
// 获取返回码,0表示成功
int retCode = jsonObject.getInt("ret");
if (0 == retCode)
{
JSONObject dataObject = jsonObject.getJSONObject("data");
JSONObject newsObject = dataObject.getJSONObject("news");
// 测试自定义控件
// retStr = newsObject.getString("body");
JSONArray bodyArray = newsObject.getJSONArray("body");
for (int i=0;i<bodyArray.length();i++)
{
JSONObject object = (JSONObject)bodyArray.opt(i);
HashMap<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put("index", object.get("index"));
hashMap.put("type", object.get("type"));
hashMap.put("value", object.get("value"));
bodyList.add(hashMap);
}
} } catch (Exception e)
{
e.printStackTrace();
}
// 测试自定义控件
// return retStr;
return bodyList;
} /**
* 更新新闻内容
*
* @author coolszy
*@date 2012-4-22
*@blog http://blog.92coding.com
*/
private class UpdateNewsThread extends Thread
{
@Override
public void run()
{
// 从网络上获取新闻
// 测试自定义控件
// String newsBody = getNewsBody();
ArrayList<HashMap<String, Object>> bodyList = getNewsBody();
Message msg = mHandler.obtainMessage();
System.out.println("@@@:"+bodyList.size());
msg.arg1 = FINISH;
msg.obj = bodyList;
mHandler.sendMessage(msg);
}
} /**
* 发表回复
*
* @author coolszy
*@date 2012-4-22
*@blog http://blog.92coding.com
*/
private class PostCommentThread extends Thread
{
@Override
public void run()
{
SyncHttp syncHttp = new SyncHttp();
String url = "http://10.0.2.2:8080/web/postComment";
List<Parameter> params = new ArrayList<Parameter>();
params.add(new Parameter("nid", mNid + ""));
params.add(new Parameter("region", "江苏省连云港市"));
params.add(new Parameter("content", mNewsReplyContent.getText().toString()));
try
{
String retStr = syncHttp.httpPost(url, params);
JSONObject jsonObject = new JSONObject(retStr);
int retCode = jsonObject.getInt("ret");
if (0 == retCode)
{
Toast.makeText(NewsDetailsActivity.this, R.string.post_success, Toast.LENGTH_SHORT).show();
mNewsReplyImgLayout.setVisibility(View.VISIBLE);
mNewsReplyEditLayout.setVisibility(View.GONE);
return;
} } catch (Exception e)
{
e.printStackTrace();
}
Toast.makeText(NewsDetailsActivity.this, R.string.post_failure, Toast.LENGTH_SHORT).show();
}
} }

三、自定义控件实现图文混排

1.1 自定义控件图文混排

package com.szy.news.view;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap; import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.Html;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ImageView.ScaleType; import com.szy.news.activity.R; /**
*@author coolszy
*@date 2012-5-1
*@blog http://blog.92coding.com
*/ public class CustomTextView extends LinearLayout
{
private Context mContext;
private TypedArray mTypedArray; public CustomTextView(Context context)
{
this(context, null);
} public CustomTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
this.mContext = context; setOrientation(LinearLayout.VERTICAL);
mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.customTextView); } public void setText(ArrayList<HashMap<String, Object>> datas)
{
for (HashMap<String, Object> hashMap : datas)
{
//如果是图片
if (hashMap.get("type").equals("image"))
{
int imageWidth = mTypedArray.getDimensionPixelOffset(R.styleable.customTextView_image_width, 100);
int imageheight = mTypedArray.getDimensionPixelOffset(R.styleable.customTextView_image_height, 100);
//创建ImageView并设置属性
ImageView imageView = new ImageView(mContext);
LayoutParams params = new LayoutParams(imageWidth, imageheight);
params.gravity = Gravity.CENTER_HORIZONTAL;//居中
imageView.setLayoutParams(params);
imageView.setImageResource(R.drawable.kuka);//默认图片
imageView.setScaleType(ScaleType.CENTER_INSIDE);
addView(imageView);
//启动线程,异步加载图片
new DownloadPicThread(imageView,hashMap.get("value").toString()).start();
}
//反之则已文本显示
else
{
//创建TextView并设置属性
TextView textView = new TextView(mContext);
textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
float textSize = mTypedArray.getDimension(R.styleable.customTextView_textSize, 16);
int textColor = mTypedArray.getColor(R.styleable.customTextView_textColor, 0xFF000000);
textView.setTextSize(textSize);
textView.setTextColor(textColor);
textView.setText(Html.fromHtml(hashMap.get("value").toString()));
addView(textView);
}
}
} private Handler mHandler = new Handler()
{
@SuppressWarnings("unchecked")
@Override
public void handleMessage(Message msg)
{
HashMap<String, Object> hashMap = (HashMap<String, Object>)msg.obj;
ImageView imageView = (ImageView)hashMap.get("imageview");
LayoutParams params = new LayoutParams(msg.arg1,msg.arg2);
params.gravity = Gravity.CENTER_HORIZONTAL;//居中
imageView.setLayoutParams(params);
Drawable drawable = (Drawable)hashMap.get("drawable");
imageView.setImageDrawable(drawable);
} }; private class DownloadPicThread extends Thread
{
private ImageView mImageView;
private String mUrl; public DownloadPicThread(ImageView imageView, String url)
{
super();
this.mImageView = imageView;
this.mUrl = url;
} public void run()
{
Drawable drawable = null;
int newImgWidth = 0;
int newImgHeigth = 0;
try
{
drawable = Drawable.createFromStream(new URL(mUrl).openStream(), "image");
newImgWidth = drawable.getIntrinsicWidth() / 3;
newImgHeigth = drawable.getIntrinsicHeight() / 3;
} catch (Exception e)
{
e.printStackTrace();
}
//为了更好的看到效果,让线程休眠2秒
SystemClock.sleep(2000);
//使用Handler更新UI
Message msg = mHandler.obtainMessage();
HashMap<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put("imageview", mImageView);
hashMap.put("drawable", drawable);
msg.obj = hashMap;
msg.arg1 = newImgWidth;
msg.arg2 = newImgHeigth;
mHandler.sendMessage(msg);
}
}
}

四、新闻客户端布局代码

4.1 使GridView控件第一项默认选中

public class CustomSimpleAdapter extends SimpleAdapter
{ public CustomSimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
{
super(context, data, resource, from, to);
} @Override
public View getView(int position, View convertView, ViewGroup parent)
{
View v = super.getView(position, convertView, parent);
//更新第一个TextView的背景
if (position==0)
{
TextView categoryTitle = (TextView)v;
categoryTitle.setBackgroundResource(R.drawable.categorybar_item_background);
categoryTitle.setTextColor(0XFFFFFFFF);
}
return v;
}
}

4.2 gridview每项切换效果,ListView添加footer

package com.szy.news.activity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import org.json.JSONArray;
import org.json.JSONObject; import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener; import com.szy.news.custom.Category;
import com.szy.news.custom.CustomSimpleAdapter;
import com.szy.news.service.SyncHttp;
import com.szy.news.service.UpdateManager;
import com.szy.news.util.DensityUtil;
import com.szy.news.util.StringUtil; public class MainActivity extends Activity
{
private final int COLUMNWIDTHPX = 55;
private final int FLINGVELOCITYPX = 800; // 滚动距离
private final int NEWSCOUNT = 5; //返回新闻数目
private final int SUCCESS = 0;//加载成功
private final int NONEWS = 1;//该栏目下没有新闻
private final int NOMORENEWS = 2;//该栏目下没有更多新闻
private final int LOADERROR = 3;//加载失败 private int mColumnWidthDip;
private int mFlingVelocityDip;
private int mCid;
private String mCatName;
private ArrayList<HashMap<String, Object>> mNewsData;
private ListView mNewsList;
private SimpleAdapter mNewsListAdapter;
private LayoutInflater mInflater;
private Button mTitlebarRefresh;
private ProgressBar mLoadnewsProgress;
private Button mLoadMoreBtn; private LoadNewsAsyncTask loadNewsAsyncTask; @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main); mInflater = getLayoutInflater();
mNewsData = new ArrayList<HashMap<String,Object>>();
mNewsList = (ListView)findViewById(R.id.newslist);
mTitlebarRefresh = (Button)findViewById(R.id.titlebar_refresh);
mLoadnewsProgress = (ProgressBar)findViewById(R.id.loadnews_progress);
mTitlebarRefresh.setOnClickListener(loadMoreListener); //把px转换成dip
mColumnWidthDip = DensityUtil.px2dip(this, COLUMNWIDTHPX);
mFlingVelocityDip = DensityUtil.px2dip(this, FLINGVELOCITYPX); //获取新闻分类
String[] categoryArray = getResources().getStringArray(R.array.categories);
//把新闻分类保存到List中
final List<HashMap<String, Category>> categories = new ArrayList<HashMap<String, Category>>();
//分割新闻类型字符串
for(int i=0;i<categoryArray.length;i++)
{
String[] temp = categoryArray[i].split("[|]");
if (temp.length==2)
{
int cid = StringUtil.String2Int(temp[0]);
String title = temp[1];
Category type = new Category(cid, title);
HashMap<String, Category> hashMap = new HashMap<String, Category>();
hashMap.put("category_title", type);
categories.add(hashMap);
}
}
//默认选中的新闻分类
mCid = 1;
mCatName ="国内";
//创建Adapter,指明映射字段
CustomSimpleAdapter categoryAdapter = new CustomSimpleAdapter(this, categories, R.layout.category_title, new String[]{"category_title"}, new int[]{R.id.category_title}); GridView category = new GridView(this);
category.setColumnWidth(mColumnWidthDip);//每个单元格宽度
category.setNumColumns(GridView.AUTO_FIT);//单元格数目
category.setGravity(Gravity.CENTER);//设置对其方式
//设置单元格选择是背景色为透明,这样选择时就不现实黄色北京
category.setSelector(new ColorDrawable(Color.TRANSPARENT));
//根据单元格宽度和数目计算总宽度
int width = mColumnWidthDip * categories.size();
LayoutParams params = new LayoutParams(width, LayoutParams.FILL_PARENT);
//更新category宽度和高度,这样category在一行显示
category.setLayoutParams(params);
//设置适配器
category.setAdapter(categoryAdapter);
//把category加入到容器中
LinearLayout categoryList = (LinearLayout) findViewById(R.id.category_layout);
categoryList.addView(category);
//添加单元格点击事件
category.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
TextView categoryTitle;
//恢复每个单元格背景色
for (int i = 0; i < parent.getChildCount(); i++)
{
categoryTitle = (TextView) (parent.getChildAt(i));
categoryTitle.setBackgroundDrawable(null);
categoryTitle.setTextColor(0XFFADB2AD);
}
//设置选择单元格的背景色
categoryTitle = (TextView) (parent.getChildAt(position));
categoryTitle.setBackgroundResource(R.drawable.categorybar_item_background);
categoryTitle.setTextColor(0XFFFFFFFF);
//获取选中的新闻分类id
mCid = categories.get(position).get("category_title").getCid();
mCatName = categories.get(position).get("category_title").getTitle();
//获取该栏目下新闻
//getSpeCateNews(mCid,mNewsData,0,true);
//通知ListView进行更新
//mNewsListAdapter.notifyDataSetChanged();
loadNewsAsyncTask = new LoadNewsAsyncTask();
loadNewsAsyncTask.execute(mCid,0,true);
}
}); // 箭头
final HorizontalScrollView categoryScrollview = (HorizontalScrollView) findViewById(R.id.category_scrollview);
Button categoryArrowRight = (Button) findViewById(R.id.category_arrow_right);
//点击箭头向左移动像素
categoryArrowRight.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
categoryScrollview.fling(DensityUtil.px2dip(MainActivity.this, mFlingVelocityDip));
}
});
//获取指定栏目的新闻列表
//getSpeCateNews(mCid,mNewsData,0,true);
mNewsListAdapter = new SimpleAdapter(this, mNewsData, R.layout.newslist_item,
new String[]{"newslist_item_title","newslist_item_digest","newslist_item_source","newslist_item_ptime"},
new int[]{R.id.newslist_item_title,R.id.newslist_item_digest,R.id.newslist_item_source,R.id.newslist_item_ptime});
//添加页脚
View loadMoreLayout = mInflater.inflate(R.layout.loadmore, null);
mNewsList.addFooterView(loadMoreLayout);
mNewsList.setAdapter(mNewsListAdapter);
//点击新闻列表项,弹出新闻详细界面
mNewsList.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Intent intent = new Intent(MainActivity.this, NewsDetailsActivity.class);
//把需要的信息放到Intent中
intent.putExtra("newsDate", mNewsData);
intent.putExtra("position", position);
intent.putExtra("categoryName", mCatName);
startActivity(intent);
}
}); mLoadMoreBtn = (Button)findViewById(R.id.loadmore_btn);
mLoadMoreBtn.setOnClickListener(loadMoreListener); loadNewsAsyncTask = new LoadNewsAsyncTask();
loadNewsAsyncTask.execute(mCid,0,true);
} /**
* 增加菜单
*/
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_item, menu);
return true;
} /**
* 处理菜单事件
*/
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
if (item.getItemId()==R.id.menu_item_update)
{
UpdateManager manager = new UpdateManager(MainActivity.this);
// 检查软件更新
manager.checkUpdate();
}
return true;
} /**
* 获取指定类型的新闻列表
* @param cid 类型ID
* @param newsList 保存新闻信息的集合
* @param startnid 分页
* @param firstTimes 是否第一次加载
*/
private int getSpeCateNews(int cid,List<HashMap<String, Object>> newsList,int startnid,Boolean firstTimes)
{
if (firstTimes)
{
//如果是第一次,则清空集合里数据
newsList.clear();
}
//请求URL和字符串
String url = "http://10.0.2.2:8080/web/getSpecifyCategoryNews";
String params = "startnid="+startnid+"&count="+NEWSCOUNT+"&cid="+cid;
SyncHttp syncHttp = new SyncHttp();
try
{
//以Get方式请求,并获得返回结果
String retStr = syncHttp.httpGet(url, params);
JSONObject jsonObject = new JSONObject(retStr);
//获取返回码,0表示成功
int retCode = jsonObject.getInt("ret");
if (0==retCode)
{
JSONObject dataObject = jsonObject.getJSONObject("data");
//获取返回数目
int totalnum = dataObject.getInt("totalnum");
if (totalnum>0)
{
//获取返回新闻集合
JSONArray newslist = dataObject.getJSONArray("newslist");
for(int i=0;i<newslist.length();i++)
{
JSONObject newsObject = (JSONObject)newslist.opt(i);
HashMap<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put("nid", newsObject.getInt("nid"));
hashMap.put("newslist_item_title", newsObject.getString("title"));
hashMap.put("newslist_item_digest", newsObject.getString("digest"));
hashMap.put("newslist_item_source", newsObject.getString("source"));
hashMap.put("newslist_item_ptime", newsObject.getString("ptime"));
hashMap.put("newslist_item_comments", newsObject.getString("commentcount"));
newsList.add(hashMap);
}
return SUCCESS;
}
else
{
if (firstTimes)
{
return NONEWS;
}
else
{
return NOMORENEWS;
}
}
}
else
{
return LOADERROR;
}
} catch (Exception e)
{
e.printStackTrace();
return LOADERROR;
}
} private OnClickListener loadMoreListener = new OnClickListener()
{
@Override
public void onClick(View v)
{
loadNewsAsyncTask = new LoadNewsAsyncTask();
switch (v.getId())
{
case R.id.loadmore_btn:
//获取该栏目下新闻
//getSpeCateNews(mCid,mNewsData,mNewsData.size(),false);
//通知ListView进行更新
//mNewsListAdapter.notifyDataSetChanged();
loadNewsAsyncTask.execute(mCid,mNewsData.size(),false);
break;
case R.id.titlebar_refresh:
loadNewsAsyncTask.execute(mCid,0,true);
break;
} }
}; private class LoadNewsAsyncTask extends AsyncTask<Object, Integer, Integer>
{ @Override
protected void onPreExecute()
{
//隐藏刷新按钮
mTitlebarRefresh.setVisibility(View.GONE);
//显示进度条
mLoadnewsProgress.setVisibility(View.VISIBLE);
//设置LoadMore Button 显示文本
mLoadMoreBtn.setText(R.string.loadmore_txt);
} @Override
protected Integer doInBackground(Object... params)
{
return getSpeCateNews((Integer)params[0],mNewsData,(Integer)params[1],(Boolean)params[2]);
} @Override
protected void onPostExecute(Integer result)
{
//根据返回值显示相关的Toast
switch (result)
{
case NONEWS:
Toast.makeText(MainActivity.this, R.string.no_news, Toast.LENGTH_LONG).show();
break;
case NOMORENEWS:
Toast.makeText(MainActivity.this, R.string.no_more_news, Toast.LENGTH_LONG).show();
break;
case LOADERROR:
Toast.makeText(MainActivity.this, R.string.load_news_failure, Toast.LENGTH_LONG).show();
break;
}
mNewsListAdapter.notifyDataSetChanged();
//显示刷新按钮
mTitlebarRefresh.setVisibility(View.VISIBLE);
//隐藏进度条
mLoadnewsProgress.setVisibility(View.GONE);
//设置LoadMore Button 显示文本
mLoadMoreBtn.setText(R.string.loadmore_btn);
}
}
}