关闭

Android demo-->网易新闻风格的RSS新闻抓取项目(二) 新闻列表刷新、天气预报、设置页面滑动开关

标签: androiddemo
322人阅读 评论(0) 收藏 举报
分类:

新闻列表刷新

自定义一个TopNewsListView继承ListView来实现下拉刷新的功能
创建下拉框的样式

<!-- ListView的头部 -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <!-- 内容 -->

    <RelativeLayout
        android:id="@+id/head_contentLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="30dp" >

        <!-- 箭头图像、进度条 -->

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true" >

            <!-- 箭头 -->

            <ImageView
                android:id="@+id/head_arrowImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/arrow" />

            <!-- 进度条 -->

            <ProgressBar
                android:id="@+id/head_progressBar"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />
        </FrameLayout>

        <!-- 提示、最近更新 -->

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:orientation="vertical" >

            <!-- 提示 -->

            <TextView
                android:id="@+id/head_tipsTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:text="下拉刷新"
                android:textColor="#404040"
                android:textSize="20sp" />

            <!-- 最近更新 -->

            <TextView
                android:id="@+id/head_lastUpdatedTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/head_tipsTextView"
                android:layout_marginTop="10dip"
                android:layout_centerHorizontal="true"
                android:text="上次更新"
                android:textColor="#606060"
                android:textSize="10sp" />
        </RelativeLayout>
    </RelativeLayout>

</LinearLayout>

仿照其他下拉刷新的demo,估计hearview的width和height

private void measureView(View child) {
        ViewGroup.LayoutParams p = child.getLayoutParams();
        if (p == null) {
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
        int lpHeight = p.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
                    MeasureSpec.EXACTLY);
        } else {
            childHeightSpec = MeasureSpec.makeMeasureSpec(0,
                    MeasureSpec.UNSPECIFIED);
        }
        child.measure(childWidthSpec, childHeightSpec);
    }

然后实现headview的隐藏,并添加到listview的头部

headContentHeight = headView.getMeasuredHeight();
        headContentWidth = headView.getMeasuredWidth();

        headView.setPadding(0, -1 * headContentHeight, 0, 0);
        headView.invalidate();
        addHeaderView(headView, null, false);

接下来通过onTouchEvent来实现刷新状态的变化

public boolean onTouchEvent(MotionEvent event) {

        if (isRefreshable) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (firstItemIndex == 0 && !isRecored) {
                    isRecored = true;
                    startY = (int) event.getY();
                    //Log.v(TAG, "在down时候记录当前位置‘");
                }
                break;

            case MotionEvent.ACTION_UP:

                if (state != REFRESHING && state != LOADING) {
                    if (state == DONE) {
                        // 什么都不做
                    }
                    if (state == PULL_To_REFRESH) {
                        state = DONE;
                        changeHeaderViewByState();

                        //Log.v(TAG, "由下拉刷新状态,到done状态");
                    }
                    if (state == RELEASE_To_REFRESH) {
                        state = REFRESHING;
                        changeHeaderViewByState();
                        onRefresh();

                        //Log.v(TAG, "由松开刷新状态,到done状态");
                    }
                }

                isRecored = false;
                isBack = false;

                break;

            case MotionEvent.ACTION_MOVE:
                int tempY = (int) event.getY();

                if (!isRecored && firstItemIndex == 0) {
                    //Log.v(TAG, "在move时候记录下位置");
                    isRecored = true;
                    startY = tempY;
                }

                if (state != REFRESHING && isRecored && state != LOADING) {

                    // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
                    // 可以松手去刷新了
                    if (state == RELEASE_To_REFRESH) {

                        setSelection(0);

                        // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
                        if (((tempY - startY) / RATIO < headContentHeight)
                                && (tempY - startY) > 0) {
                            state = PULL_To_REFRESH;
                            changeHeaderViewByState();

                            //Log.v(TAG, "由松开刷新状态转变到下拉刷新状态");
                        }
                        // 一下子推到顶了
                        else if (tempY - startY <= 0) {
                            state = DONE;
                            changeHeaderViewByState();

                            //Log.v(TAG, "由松开刷新状态转变到done状态");
                        }
                        // 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
                        else {
                            // 不用进行特别的操作,只用更新paddingTop的值就行了
                        }
                    }
                    // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
                    if (state == PULL_To_REFRESH) {

                        setSelection(0);

                        // 下拉到可以进入RELEASE_TO_REFRESH的状态
                        if ((tempY - startY) / RATIO >= headContentHeight) {
                            state = RELEASE_To_REFRESH;
                            isBack = true;
                            changeHeaderViewByState();

                            //Log.v(TAG, "由done或者下拉刷新状态转变到松开刷新");
                        }
                        // 上推到顶了
                        else if (tempY - startY <= 0) {
                            state = DONE;
                            changeHeaderViewByState();

                            //Log.v(TAG, "由DOne或者下拉刷新状态转变到done状态");
                        }
                    }

                    // done状态下
                    if (state == DONE) {
                        if (tempY - startY > 0) {
                            state = PULL_To_REFRESH;
                            changeHeaderViewByState();
                        }
                    }

                    // 更新headView的size
                    if (state == PULL_To_REFRESH) {
                        headView.setPadding(0, -1 * headContentHeight + (tempY - startY) / RATIO, 0, 0);

                    }

                    // 更新headView的paddingTop
                    if (state == RELEASE_To_REFRESH) {
                        headView.setPadding(0, (tempY - startY) / RATIO - headContentHeight, 0, 0);
                    }

                }

                break;
            }
        }

        return super.onTouchEvent(event);
    }

    // 当状态改变时候,调用该方法,以更新界面
    private void changeHeaderViewByState() {
        switch (state) {
        case RELEASE_To_REFRESH:
            arrowImageView.setVisibility(View.VISIBLE);
            progressBar.setVisibility(View.GONE);
            tipsTextview.setVisibility(View.VISIBLE);
            lastUpdatedTextView.setVisibility(View.VISIBLE);

            arrowImageView.clearAnimation();
            arrowImageView.startAnimation(animation);

            tipsTextview.setText("松开刷新");

            //Log.v(TAG, "当前状态,松开刷新");
            break;
        case PULL_To_REFRESH:
            progressBar.setVisibility(View.GONE);
            tipsTextview.setVisibility(View.VISIBLE);
            lastUpdatedTextView.setVisibility(View.VISIBLE);
            arrowImageView.clearAnimation();
            arrowImageView.setVisibility(View.VISIBLE);
            // 是由RELEASE_To_REFRESH状态转变来的
            if (isBack) {
                isBack = false;
                arrowImageView.clearAnimation();
                arrowImageView.startAnimation(reverseAnimation);

                tipsTextview.setText("下拉刷新");
            } else {
                tipsTextview.setText("下拉刷新");
            }
            //Log.v(TAG, "当前状态,下拉刷新");
            break;

        case REFRESHING:

            headView.setPadding(0, 0, 0, 0);

            progressBar.setVisibility(View.VISIBLE);
            arrowImageView.clearAnimation();
            arrowImageView.setVisibility(View.GONE);
            tipsTextview.setText("正在刷新...");
            lastUpdatedTextView.setVisibility(View.VISIBLE);

            //Log.v(TAG, "当前状态,正在刷新...");
            break;
        case DONE:
            headView.setPadding(0, -1 * headContentHeight, 0, 0);

            progressBar.setVisibility(View.GONE);
            arrowImageView.clearAnimation();
            arrowImageView.setImageResource(R.drawable.arrow);
            tipsTextview.setText("下拉刷新");
            lastUpdatedTextView.setVisibility(View.VISIBLE);

            //Log.v(TAG, "当前状态,done");
            break;
        }
    }

最后开放一个OnRefreshistener接口来让外界接入进行刷新

public void setonRefreshListener(OnRefreshListener refreshListener) {
        this.refreshListener = refreshListener;
        isRefreshable = true;
    }

    public interface OnRefreshListener {
        public void onRefresh();
    }
private void topNewsListViewRefresh(){
        topNewsListView.setonRefreshListener(new TopNewsListView.OnRefreshListener() {

            public void onRefresh() {
                new AsyncTask<Void, Void, Void>() {
                    protected Void doInBackground(Void... params) {
                        try {
                            Thread.sleep(1000);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        //handleList();
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Void result) {
                        listAdapterTop.notifyDataSetChanged();
                        topNewsListView.onRefreshComplete();
                    }

                }.execute();
            }
        }); 
    }

天气预报

天气预报页面展示

天气预报页面的弹出效果实现从右侧滑入

<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="500"
        android:fromXDelta="100%p"
        android:toXDelta="0" />
</set>

<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="500"
        android:fromXDelta="0"
        android:toXDelta="-100%p" />
</set>

overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);

城市定位

使用百度定位SDK来获取当前所在城市

public class CityLocation {
    public LocationClient locationClient = null;
    private Context con = null;
    private boolean flag = true;

    public void getCituLocation(Context context){
        this.con = context;

        locationClient = new LocationClient(con);
        locationClient.registerLocationListener(new BDLocationListener() {

            @Override
            public void onReceivePoi(BDLocation arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onReceiveLocation(BDLocation arg0) {
                // TODO Auto-generated method stub
                if (arg0 != null)
                {
                    StringBuffer sb = new StringBuffer(128);// 接受服务返回的缓冲区
                    sb.append(arg0.getCity());// 获得城市
                    MainActivity.cityHanzi = sb.toString().trim();
                    //System.out.println(MainActivity.cityLocation);
                    if (flag) {
                        MainActivity.cityLocationMsgHandler.sendEmptyMessage(0);
                        flag = false;
                    }


                } else
                {
                    return;
                }
            }
        }); // 注册监听函数

        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true);// 打开GPS
        option.setAddrType("all");// 返回的定位结果包含地址信息
        option.setCoorType("bd09ll");// 返回的定位结果是百度经纬度,默认值gcj02
        option.setScanSpan(3000);// 设置发起定位请求的间隔时间为3000ms
        option.disableCache(false);// 禁止启用缓存定位
        option.setPriority(LocationClientOption.NetWorkFirst);// 网络定位优先
        locationClient.setLocOption(option);// 使用设置
        locationClient.start();// 开启定位SDK
        locationClient.requestLocation();// 开始请求位置
    }
}

创建一个将汉字转换成拼音的类

public class GetPinyinFromHanzi {
    private StringBuffer city = null;
    private String returnCity = null;

    private StringBuffer pinyinForAll = null;
    private String returnPinyinForAll = null;

    public String hanziToPinYin(String hanzi){
        city = new StringBuffer();

        String citySplit[] = hanzi.split("市");
        String cityWeNeed = citySplit[0];

        for (int i = 0; i < cityWeNeed.length(); i++) {
            String citypinyin = new String();
            citypinyin = toPinYin(cityWeNeed.charAt(i));
            city.append(citypinyin);
        }

        if (city.toString().contains("dou")) 
            returnCity = city.toString().replaceAll("dou", "du");
        else
            returnCity = city.toString();

        return returnCity;
    }

    public String hanziToPinYinForAll(String hanzi){
        pinyinForAll = new StringBuffer();

        for (int i = 0; i < hanzi.length(); i++) {
            String pinyin = new String();
            pinyin = toPinYin(hanzi.charAt(i));
            pinyinForAll.append(pinyin);
        }

        returnPinyinForAll = pinyinForAll.toString();
        return returnPinyinForAll;
    }

    private String toPinYin(char hanzi){
        HanyuPinyinOutputFormat hanyuPinyin = new HanyuPinyinOutputFormat();
        hanyuPinyin.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        hanyuPinyin.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        hanyuPinyin.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);
        String[] pinyinArray=null;
        try {
            //是否在汉字范围内
            if(hanzi>=0x4e00 && hanzi<=0x9fa5){
                pinyinArray = PinyinHelper.toHanyuPinyinStringArray(hanzi, hanyuPinyin);
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            e.printStackTrace();
        }
        //将获取到的拼音返回
        return pinyinArray[0];
    }
}

获取到当前城市的拼音,添加到xml路径中去,用于xml数据请求,最后将请求到的数据放入weatherItemList,通过weatherItemList来进行天气页面的数据展示。

设置页面滑动开关

创建一个自定义滑动按钮SlipButton

public class SlipButton extends View implements OnTouchListener
{
    private boolean NowChoose = false;// 记录当前按钮是否打开,true为打开,flase为关闭
    private boolean isChecked;
    private boolean OnSlip = false;// 记录用户是否在滑动的变量
    private float DownX, NowX;// 按下时的x,当前的x
    private Rect Btn_On, Btn_Off;// 打开和关闭状态下,游标的Rect .
    private boolean isChgLsnOn = false;
    private OnChangedListener ChgLsn;
    private Bitmap bg_on, bg_off, slip_btn;

    public SlipButton(Context context)
    {
        super(context);
        init();
    }

    public SlipButton(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init();
    }

    public SlipButton(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        init();
    }

    private void init()
    {// 初始化

        bg_on = BitmapFactory.decodeResource(getResources(), R.drawable.split_left_1);
        bg_off = BitmapFactory.decodeResource(getResources(), R.drawable.split_right_1);
        slip_btn = BitmapFactory.decodeResource(getResources(), R.drawable.split_1);
        Btn_On = new Rect(0, 0, slip_btn.getWidth(), slip_btn.getHeight());
        Btn_Off = new Rect(bg_off.getWidth() - slip_btn.getWidth(), 0, bg_off.getWidth(),
                slip_btn.getHeight());
        setOnTouchListener(this);// 设置监听器,也可以直接复写OnTouchEvent
    }

    @Override
    protected void onDraw(Canvas canvas)
    {// 绘图函数

        super.onDraw(canvas);

        Matrix matrix = new Matrix();
        Paint paint = new Paint();
        float x;

        if (NowX < (bg_on.getWidth() / 2))// 滑动到前半段与后半段的背景不同,在此做判断
        {
            x = NowX - slip_btn.getWidth() / 2;
            canvas.drawBitmap(bg_off, matrix, paint);// 画出关闭时的背景
        }

        else
        {
            x = bg_on.getWidth() - slip_btn.getWidth() / 2;
            canvas.drawBitmap(bg_on, matrix, paint);// 画出打开时的背景
        }

        if (OnSlip)// 是否是在滑动状态,

        {
            if (NowX >= bg_on.getWidth())// 是否划出指定范围,不能让游标跑到外头,必须做这个判断

                x = bg_on.getWidth() - slip_btn.getWidth() / 2;// 减去游标1/2的长度...

            else if (NowX < 0)
            {
                x = 0;
            }
            else
            {
                x = NowX - slip_btn.getWidth() / 2;
            }
        }
        else
        {// 非滑动状态

            if (NowChoose)// 根据现在的开关状态设置画游标的位置
            {
                x = Btn_Off.left;
                canvas.drawBitmap(bg_on, matrix, paint);// 初始状态为true时应该画出打开状态图片
            }
            else
                x = Btn_On.left;
        }
        if (isChecked)
        {
            canvas.drawBitmap(bg_on, matrix, paint);
            x = Btn_Off.left;
            isChecked = !isChecked;
        }

        if (x < 0)// 对游标位置进行异常判断...
            x = 0;
        else if (x > bg_on.getWidth() - slip_btn.getWidth())
            x = bg_on.getWidth() - slip_btn.getWidth();
        canvas.drawBitmap(slip_btn, x, 0, paint);// 画出游标.

    }

    public boolean onTouch(View v, MotionEvent event)
    {
        switch (event.getAction())
        // 根据动作来执行代码

        {
        case MotionEvent.ACTION_MOVE:// 滑动
            NowX = event.getX();
            break;

        case MotionEvent.ACTION_DOWN:// 按下

            if (event.getX() > bg_on.getWidth() || event.getY() > bg_on.getHeight())
                return false;
            OnSlip = true;
            DownX = event.getX();
            NowX = DownX;
            break;

        case MotionEvent.ACTION_CANCEL: // 移到控件外部

            OnSlip = false;
            boolean choose = NowChoose;
            if (NowX >= (bg_on.getWidth() / 2))
            {
                NowX = bg_on.getWidth() - slip_btn.getWidth() / 2;
                NowChoose = true;
            }
            else
            {
                NowX = NowX - slip_btn.getWidth() / 2;
                NowChoose = false;
            }
            if (isChgLsnOn && (choose != NowChoose)) // 如果设置了监听器,就调用其方法..
                ChgLsn.OnChanged(NowChoose);
            break;
        case MotionEvent.ACTION_UP:// 松开

            OnSlip = false;
            boolean LastChoose = NowChoose;

            if (event.getX() >= (bg_on.getWidth() / 2))
            {
                NowX = bg_on.getWidth() - slip_btn.getWidth() / 2;
                NowChoose = true;
            }

            else
            {
                NowX = NowX - slip_btn.getWidth() / 2;
                NowChoose = false;
            }

            if (isChgLsnOn && (LastChoose != NowChoose)) // 如果设置了监听器,就调用其方法..

                ChgLsn.OnChanged(NowChoose);
            break;
        default:
        }
        invalidate();// 重画控件
        return true;
    }

    public void SetOnChangedListener(OnChangedListener l)
    {// 设置监听器,当状态修改的时候
        isChgLsnOn = true;
        ChgLsn = l;
    }

    public interface OnChangedListener
    {
        abstract void OnChanged(boolean CheckState);
    }

    public void setCheck(boolean isChecked)
    {
        this.isChecked = isChecked;
        NowChoose = isChecked;
    }
}

项目名称: NewsReader

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:5939次
    • 积分:265
    • 等级:
    • 排名:千里之外
    • 原创:21篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条