• 团队项目-第一阶段冲刺-1


    一、说在前面

      昨天

    ---------------

      今天

    1、环境搭建;2、设计思路

    遇到问题

    请求到的参数的出现中文乱码问题

    二、分析新闻列表界面包含的功能

    1、下拉搜索提示框。1.5h

    2、发布自己身边的“新闻”。1h

    3、置顶、最热新闻图片轮播。0.7h

    4、新闻列表(置顶、下拉刷新、点击事件)0.8h

    三、冲刺成果

    2、新闻列表和点击事件:

    一、设计思路

    1、数据源:新闻api:https://www.jianshu.com/p/c54e25349b77。

    2、网络请求:封装一个网络请求工具(使用HttpURLConnection)发送URL,返回数据string。

    3、数据获取:使用 AsyncTask 异步加载网络数据,及调用工具类的工具函数。

    4、数据解析:根据返回的数据和需要的数据,处理从网上获取的字符串,并使用Gson工具将处理后的字符串转换为我们熟悉的java对象。 

    5、网络图片展示:自定义一个imageView,用于展示网络图片。(我的是:传入一个网络图片的网址->展示该网络图片)

    6、数据展示:使用RecycleView展示列表数据(包括新闻图片、标题、概要、时间)。

    7、分析可知需添加依赖:

    dependencies {
    
        implementation 'androidx.recyclerview:recyclerview:1.1.0'
        implementation 'com.google.code.gson:gson:2.8.6'
    
    }

    二、效果

    三、源代码

    1、用于发送网络请求的工具类:

    package com.me.androidstudy2.utils;
    
    import android.util.Log;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class HttpUtil {
        /**
         * 返回json
         * @param setUrl
         * @return
         */
        public static String setUrl(String setUrl){
            try {
                URL url = new URL(setUrl);
                HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                conn.setConnectTimeout(5000);
                conn.setRequestMethod("GET");
                int responseCode = conn.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK){
                    InputStream inputStream = conn.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                    BufferedReader reader = new BufferedReader(inputStreamReader);
                    StringBuffer stringBuffer = new StringBuffer();
                    String string = reader.readLine();
                    while (string != null) {
                        stringBuffer.append(string);
                        string = reader.readLine();
                    }
                    Log.e("web",stringBuffer.toString());
                    return stringBuffer.toString();
                }else{
                    Log.e("web",responseCode+"");
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
        }
    }
    View Code

    2、自定义一个imageView,用于展示网络图片。

    package com.me.androidstudy2.view;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Handler;
    import android.os.Message;
    import android.util.AttributeSet;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    /**
     * 使用时只需调用setImageURL(图片网址);即可
     */
    @SuppressLint("AppCompatCustomView")
    public class MyImageView extends ImageView {
        public static final int GET_DATA_SUCCESS = 1;
        public static final int NETWORK_ERROR = 2;
        public static final int SERVER_ERROR = 3;
        //子线程不能操作UI,通过Handler设置图片
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what){
                    case GET_DATA_SUCCESS:
                        Bitmap bitmap = (Bitmap) msg.obj;
                        setImageBitmap(bitmap);
                        break;
                    case NETWORK_ERROR:
                        Toast.makeText(getContext(),"网络连接失败",Toast.LENGTH_SHORT).show();
                        break;
                    case SERVER_ERROR:
                        Toast.makeText(getContext(),"服务器发生错误",Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        };
    
        public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public MyImageView(Context context) {
            super(context);
        }
    
        public MyImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        //设置网络图片
        public void setImageURL(final String path) {
            //开启一个线程用于联网
            new Thread() {
                @Override
                public void run() {
                    try {
                        //把传过来的路径转成URL
                        URL url = new URL(path);
                        //获取连接
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        //使用GET方法访问网络
                        connection.setRequestMethod("GET");
                        //超时时间为10秒
                        connection.setConnectTimeout(10000);
                        //获取返回码
                        int code = connection.getResponseCode();
                        if (code == 200) {
                            InputStream inputStream = connection.getInputStream();
                            //使用工厂把网络的输入流生产Bitmap
                            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                            //利用Message把图片发给Handler
                            Message msg = Message.obtain();
                            msg.obj = bitmap;
                            msg.what = GET_DATA_SUCCESS;
                            handler.sendMessage(msg);
                              inputStream.close();
                        }else {
                            //服务启发生错误
                            handler.sendEmptyMessage(SERVER_ERROR);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                        //网络连接错误
                        handler.sendEmptyMessage(NETWORK_ERROR);
                    }
                }
            }.start();
        }
    
    }
    View Code

    3、activity的逻辑代码

    package com.me.androidstudy2;
    
    import android.app.Activity;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import com.google.gson.Gson;
    import com.me.androidstudy2.adapter.NewAdapter;
    import com.me.androidstudy2.domain.News;
    import com.me.androidstudy2.utils.HttpUtil;
    
    public class XwActivity extends Activity {
        private News news = new News();
        private RecyclerView recyclerView;
        private SentUrlTask sentUrlTask;
        private NewAdapter adapter = new NewAdapter();
    
        public void initView(){
            recyclerView = findViewById(R.id.rv_news);
        }
    
        public void action(){
            sentUrlTask = new SentUrlTask("http://3g.163.com/touch/reconstruct/article/list/BBM54PGAwangning/0-20.html");
            sentUrlTask.execute();
    
        }
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_xw);
            initView();
            action();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (sentUrlTask != null) {
                sentUrlTask.cancel(true);
            }
        }
    
        private class SentUrlTask extends AsyncTask<Void,Void,String> {
    
            private  String url;
    
            public SentUrlTask(String url) {
                this.url = url;
            }
    
            @Override
            protected String doInBackground(Void... voids) {
                return HttpUtil.setUrl(url);
            }
    
            @Override
            protected void onPostExecute(@NonNull String s) {
                super.onPostExecute(s);
                Gson gson = new Gson();
                String ss = s.substring(9,s.length()-1);
                news = gson.fromJson(ss, News.class);
                adapter.setData(news.getBBM54PGAwangning());
                recyclerView.setAdapter(adapter);
                recyclerView.setLayoutManager(new LinearLayoutManager(XwActivity.this));
                recyclerView.setAdapter(adapter);
                Log.e("new-ss:",news.getBBM54PGAwangning().get(0).getTitle());
            }
        }
    
    }
    View Code

    4、新闻列表的适配器:

    1)MyViewHolder

    package com.me.androidstudy2.adapter;
    
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;
    
    import com.me.androidstudy2.R;
    import com.me.androidstudy2.view.MyImageView;
    
    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView title ;
        TextView content ;
        TextView date ;
        MyImageView img ;
    
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            title = itemView.findViewById(R.id.tv_title);
            content = itemView.findViewById(R.id.tv_content);
            date = itemView.findViewById(R.id.tv_date);
            img = itemView.findViewById(R.id.iv_new);
        }
    }
    View Code

    2)NewAdapter

    package com.me.androidstudy2.adapter;
    
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;
    
    import com.me.androidstudy2.R;
    import com.me.androidstudy2.domain.New;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class NewAdapter extends RecyclerView.Adapter<MyViewHolder> {
        List<New> data ;
    
        public List<New> getData() {
            return data;
        }
    
        public void setData(List<New> data) {
            this.data = data;
        }
    
        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
            View itemView = layoutInflater.inflate(R.layout.item_layout,parent,false);
            return new MyViewHolder(itemView);
        }
    
        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            holder.img.setImageURL(data.get(position).getImgsrc());
            holder.content.setText(data.get(position).getDigest());
            holder.title.setText(data.get(position).getTitle());
            holder.date.setText(data.get(position).getPtime());
        }
    
        @Override
        public int getItemCount() {
            return data.size();
        }
    }
    View Code

    5、新闻实体:

    1)New

    package com.me.androidstudy2.domain;
    
    public class New {
        private String title;
        private String imgsrc;
        private String digest;
        private String ptime;
    
        public String getPtime() {
            return ptime;
        }
    
        public void setPtime(String ptime) {
            this.ptime = ptime;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getImgsrc() {
            return imgsrc;
        }
    
        public void setImgsrc(String imgsrc) {
            this.imgsrc = imgsrc;
        }
    
        public String getDigest() {
            return digest;
        }
    
        public void setDigest(String digest) {
            this.digest = digest;
        }
    }
    View Code

    2)News

    package com.me.androidstudy2.domain;
    
    import java.util.List;
    
    public class News {
        private List<New> BBM54PGAwangning;
        private List<New> BA10TA81wangning;
        private List<New> BA8E6OEOwangning;
        private List<New> BA8EE5GMwangning;
        private List<New> BAI67OGGwangning;
        private List<New> BA8D4A3Rwangning;
        private List<New> BAI6I0O5wangning;
        private List<New> BAI6JOD9wangning;
        private List<New> BA8F6ICNwangning;
        private List<New> BAI6RHDKwangning;
        private List<New> BA8FF5PRwangning;
        private List<New> BDC4QSV3wangning;
        private List<New> BEO4GINLwangning;
    
        public List<New> getBA10TA81wangning() {
            return BA10TA81wangning;
        }
    
        public void setBA10TA81wangning(List<New> BA10TA81wangning) {
            this.BA10TA81wangning = BA10TA81wangning;
        }
    
        public List<New> getBA8E6OEOwangning() {
            return BA8E6OEOwangning;
        }
    
        public void setBA8E6OEOwangning(List<New> BA8E6OEOwangning) {
            this.BA8E6OEOwangning = BA8E6OEOwangning;
        }
    
        public List<New> getBA8EE5GMwangning() {
            return BA8EE5GMwangning;
        }
    
        public void setBA8EE5GMwangning(List<New> BA8EE5GMwangning) {
            this.BA8EE5GMwangning = BA8EE5GMwangning;
        }
    
        public List<New> getBAI67OGGwangning() {
            return BAI67OGGwangning;
        }
    
        public void setBAI67OGGwangning(List<New> BAI67OGGwangning) {
            this.BAI67OGGwangning = BAI67OGGwangning;
        }
    
        public List<New> getBA8D4A3Rwangning() {
            return BA8D4A3Rwangning;
        }
    
        public void setBA8D4A3Rwangning(List<New> BA8D4A3Rwangning) {
            this.BA8D4A3Rwangning = BA8D4A3Rwangning;
        }
    
        public List<New> getBAI6I0O5wangning() {
            return BAI6I0O5wangning;
        }
    
        public void setBAI6I0O5wangning(List<New> BAI6I0O5wangning) {
            this.BAI6I0O5wangning = BAI6I0O5wangning;
        }
    
        public List<New> getBAI6JOD9wangning() {
            return BAI6JOD9wangning;
        }
    
        public void setBAI6JOD9wangning(List<New> BAI6JOD9wangning) {
            this.BAI6JOD9wangning = BAI6JOD9wangning;
        }
    
        public List<New> getBA8F6ICNwangning() {
            return BA8F6ICNwangning;
        }
    
        public void setBA8F6ICNwangning(List<New> BA8F6ICNwangning) {
            this.BA8F6ICNwangning = BA8F6ICNwangning;
        }
    
        public List<New> getBAI6RHDKwangning() {
            return BAI6RHDKwangning;
        }
    
        public void setBAI6RHDKwangning(List<New> BAI6RHDKwangning) {
            this.BAI6RHDKwangning = BAI6RHDKwangning;
        }
    
        public List<New> getBA8FF5PRwangning() {
            return BA8FF5PRwangning;
        }
    
        public void setBA8FF5PRwangning(List<New> BA8FF5PRwangning) {
            this.BA8FF5PRwangning = BA8FF5PRwangning;
        }
    
        public List<New> getBDC4QSV3wangning() {
            return BDC4QSV3wangning;
        }
    
        public void setBDC4QSV3wangning(List<New> BDC4QSV3wangning) {
            this.BDC4QSV3wangning = BDC4QSV3wangning;
        }
    
        public List<New> getBEO4GINLwangning() {
            return BEO4GINLwangning;
        }
    
        public void setBEO4GINLwangning(List<New> BEO4GINLwangning) {
            this.BEO4GINLwangning = BEO4GINLwangning;
        }
    
        public List<New> getBBM54PGAwangning() {
            return BBM54PGAwangning;
        }
    
        public void setBBM54PGAwangning(List<New> BBM54PGAwangning) {
            this.BBM54PGAwangning = BBM54PGAwangning;
        }
    }
    View Code

    6、新闻项的布局

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal" android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <com.me.androidstudy2.view.MyImageView
            android:id="@+id/iv_new"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_margin="4dp"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:padding="4dp"
            android:orientation="vertical">
            <TextView
                android:id="@+id/tv_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="24dp"
                android:maxLines="1"
                android:text="title"/>
            <TextView
                android:id="@+id/tv_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="13dp"
                android:maxLines="3"
                android:text="content"/>
            <TextView
                android:id="@+id/tv_date"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="right"
                android:textSize="10dp"
                android:layout_marginRight="5dp"
                android:text="content"/>
        </LinearLayout>
    
    </LinearLayout>
    View Code

    7、activity的布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_news"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
    View Code

    2、简单轮播图:

    一、效果:手动轮播、自动轮播皆可。

     

     二、设计思路:

    1、自定义view,继承viewGroup类

    2、求出子视图的个数,子视图高度,子视图宽度。假设轮播图的每一张图片大小相等根据第一个子视图的宽度和子视图的个数求出并设置viewGroup的宽高。

    3、在onLayout方法中动态设置viewGroup的布局(绘制)。

    4、事件设置:让onInterceptTouchEvent返回true,让onTouchEvent来处理事件,按下、移动、抬起需要做的事情。

    5、使用Scroller来完成自动轮播。(当按下没有移动时停止自动轮播,抬起是重新开始轮播)。

    6、通过一个接口实现单击事件和参数传递(用一个布尔变量表示是否是单击事件在按下时设置为true,移动时设置为false,在抬起时判断是否需要处理单击事件)。

    三、代码

    自定义的ViewGroup:

    package com.me.androidstudy2.view;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.os.Handler;
    import android.os.Message;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Scroller;
    
    import androidx.annotation.NonNull;
    
    import com.me.androidstudy2.jk.ImgViewGroupLister;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class ImgViewGroup extends ViewGroup {
        private int child; //子视图个数
        private int childWidth; // 子视图宽
        private int childHeight; //子视图高
        private int x;
        private int index = 0;
        private Scroller scroller;
        private Timer timer = new Timer();
        private TimerTask timerTask ;
        private boolean isAtuo = true; //默认开启自动轮播
        private ImgViewGroupLister lister ;
    
        private boolean isClick;
    
        public ImgViewGroupLister getLister() {
            return lister;
        }
    
        public void setLister(ImgViewGroupLister lister) {
            this.lister = lister;
        }
    
    
    
        @SuppressLint("HandlerLeak")
        private Handler handler = new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                switch (msg.what){
                    case 0:
                        if (++index >= child ){ //到达最后一张图时,从初开始
                            index = 0;
                        }
                        scrollTo(childWidth * index,0);
                        break;
                }
            }
        };
    
    
        public ImgViewGroup(Context context) {
            super(context);
            InitObj();
        }
    
        public ImgViewGroup(Context context, AttributeSet attrs) {
            super(context, attrs);
            InitObj();
        }
    
        public ImgViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            InitObj();
        }
    
        public void InitObj(){
            scroller = new Scroller(getContext());
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    if(isAtuo){
                        handler.sendEmptyMessage(0);
                    }
                }
            };
            timer.schedule(timerTask,100,2000);
        }
    
        @Override
        public void computeScroll() {
            super.computeScroll();
            if (scroller.computeScrollOffset()){
                scrollTo(scroller.getCurrX(),0);
                invalidate();
            }
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            //1、求出子视图的个数
            child = getChildCount();
    
            if (child == 0){
                setMeasuredDimension(0,0);
            }else{
                measureChildren(widthMeasureSpec,heightMeasureSpec);
                View view = getChildAt(0);
    
                childHeight = view.getMeasuredHeight();
                childWidth = view.getMeasuredWidth();
                int width = childWidth * child;
                int height = childHeight;
                //设置viewGroup的高度和宽度
                setMeasuredDimension(width,height);
            }
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
    
            if (changed){
                int left = 0;
                for (int i = 0; i < child; i++) {
                    View view = getChildAt(i);
    
                    view.layout(left, 0, left+childWidth, childHeight);
                    left += childWidth;
                }
            }
        }
    
        /**
         * 事件的传递
         * 事件拦截 :
         */
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            return true;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:  //按下
                    isAtuo = false;
                    if (!scroller.isFinished()){
                        scroller.abortAnimation();
                    }
                    x = (int) event.getX();
                    isClick = true;
                    break;
                case MotionEvent.ACTION_MOVE: //移动
                    int moveX = (int) event.getX();
                    int d = moveX - x;
                    scrollBy(-d,0);
                    x = moveX;
                    isClick = false;
                    break;
                case MotionEvent.ACTION_UP: //抬起
    
                    int scrollX = getScrollX();
                    index = (scrollX + childWidth / 2) /childWidth;  //求下标,四舍五入
                    Log.e("xw",index + "");
                    if(index < 0){  //最左边
                        index = 0;
                    }else if(index > child - 1){ //最右边
                        index = child - 1;
                    }
    
                    if (isClick){
                        lister.clickImg("http://u" + index + ".php");
                    }else{
                        //                scrollTo(index * childWidth,0);
                        int dx = index * childWidth -scrollX;
                        scroller.startScroll(scrollX,0,dx,0);
                        postInvalidate();
                    }
    
                    isAtuo = true;
                    break;
    
                default:
                    break;
            }
            return true;
    
        }
    }
    View Code

    单击事件的接口:

    package com.me.androidstudy2.jk;
    
    public interface ImgViewGroupLister {
        void clickImg(String url);
    }
    View Code

    active:

    package com.me.androidstudy2;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    import com.me.androidstudy2.jk.ImgViewGroupLister;
    import com.me.androidstudy2.view.ImgViewGroup;
    
    
    public class MainActivity extends AppCompatActivity implements ImgViewGroupLister {
        private ImgViewGroup imgViewGroup ;
    
        public void initView(){
            imgViewGroup = findViewById(R.id.img_view_group);
        }
    
        public void action(){
            imgViewGroup.setLister(this);
            int [] ids = new int[] {
              R.drawable.xw7,
              R.drawable.xw4,
              R.drawable.xw2
            };
            for (int i = 0; i < ids.length; i++) {
                ImageView img = new ImageView(this);
                img.setBackgroundResource(ids[i]);
                imgViewGroup.addView(img);
            }
        }
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            action();
    
        }
    
        @Override
        public void clickImg(String url) {
            Toast.makeText(this,"url = " + url,Toast.LENGTH_SHORT).show();
        }
    }
    View Code
  • 相关阅读:
    程序员数学
    [topcoder]FlowerGarden
    [leetcode]Trapping Rain Water
    [leetcode]Gray Code
    [leetcode]Unique Paths II
    hdu 4112 Break the Chocolate(ceil floor)
    【转】博弈-翻硬币游戏
    POJ 3710 Christmas Game
    hdu 3590 PP and QQ
    博弈进阶
  • 原文地址:https://www.cnblogs.com/20183544-wangzhengshuai/p/12708830.html
Copyright © 2020-2023  润新知