zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    }
    View Code
  • 相关阅读:
    thymeleaf对数据库HTML内容解析
    最近用ajax+七牛云+springboot上传图片
    设计二级评论记录
    数据结构实验8:内部排序
    数据结构实验7:实现二分查找、二叉排序(查找)树和AVL树
    数据结构实验6:C++实现二叉树类
    C++实现链队类——合肥工业大学数据结构实验5:链式队列
    数据结构实验4:C++实现循环队列
    数据结构实验3:C++实现顺序栈类与链栈类
    数据结构实验2:C++实现单链表类
  • 原文地址:https://www.cnblogs.com/lbangel/p/3532172.html
Copyright © 2011-2022 走看看