Android学习笔记_48_若水新闻客户端源码剖析
一、新闻客户端布局代码
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); } } }