一個小時打造新聞app

BaiCasner 8年前發布 | 51K 次閱讀 安卓開發 Android開發 移動開發

前言

作為一個新手,學完基礎總想做點什么東西出來。于是我試著去模仿那些優秀的開源作品。

模仿作品: LookLook開源項目

經過一些波折和學習,寫下模仿過程。

一個小時打造新聞app

實際上我花了大概三天才弄懂所有的東西,不過有了經驗確實可以在一個小時里完成。

使用框架

rxjava和retrofit以及一個開源擴展的recyclerview和注解框架butterknife

集體依賴如下:

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.android.support:design:24.2.1'
    testCompile 'junit:junit:4.12'
    //依賴注解
    //依賴添加
    compile 'com.jakewharton:butterknife:8.4.0'
    apt 'com.jakewharton:butterknife-compiler:8.4.0'
    compile 'com.google.code.gson:gson:2.7'
    //高級的recyclerview
    compile 'com.jude:easyrecyclerview:4.2.3'
    compile 'com.android.support:recyclerview-v7:24.2.0'
    //rxjava
    compile 'com.squareup.retrofit2:retrofit-converters:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'io.reactivex:rxandroid:1.2.1'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.1.0'
    compile 'com.github.bumptech.glide:glide:3.7.0'
}

開始制作app

界面制作

新建項目,選擇模板---->調整模板

菜單調整

可以看到有menu里面兩個文件

一個是主菜單,顯示在Toobar上面

另一個是抽屜的菜單,按需修改即可。

activity_main_drawer.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android=";

<group android:checkableBehavior="single">

    <item
        android:id="@+id/nav_camera"
        android:icon="@drawable/ic_menu_slideshow"
        android:title="新聞精選" />
    <item
        android:id="@+id/nav_gallery"
        android:icon="@drawable/ic_face_black_24dp"
        android:title="輕松一刻" />
    <item
        android:id="@+id/nav_slideshow"
        android:icon="@drawable/ic_menu_gallery"
        android:title="每日美圖" />
    <item
        android:id="@+id/nav_manage"
        android:icon="@drawable/ic_menu_manage"
        android:title="應用推薦" />
</group>

<item android:title="其他">
    <menu>
        <item
            android:id="@+id/nav_share"
            android:icon="@drawable/ic_menu_share"
            android:title="軟件分享" />
        <item
            android:id="@+id/nav_send"
            android:icon="@drawable/ic_menu_send"
            android:title="軟件關于" />
    </menu>
</item>

</menu></code></pre>

抽屜除了menu還有上面一部分,可以設置頭像和簽名。

nav_header_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="

<ImageView
    android:layout_gravity="center"
    android:id="@+id/imageView"
    android:layout_width="100dp"
    android:layout_height="100dp"
    app:srcCompat="@drawable/ic_app_icon" />

<TextView
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="一日之計在于晨,一年之計在于春。"
    android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

<TextView
    android:gravity="center"
    android:id="@+id/textView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="1458476478@qq.com" />

</LinearLayout></code></pre>

主界面大概這就可以了,剩下的就是要動態添加fragement到FragLayout里面去。

數據獲取

首先新建fragment_news,布局文件只需要一個 EasyRecyclerView 即可

添加依賴

//高級的recyclerview
    compile 'com.jude:easyrecyclerview:4.2.3'
    compile 'com.android.support:recyclerview-v7:24.2.0'
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <com.jude.easyrecyclerview.EasyRecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:recyclerClipToPadding="true"
        app:recyclerPadding="8dp"
        app:recyclerPaddingBottom="8dp"
        app:recyclerPaddingLeft="8dp"
        app:recyclerPaddingRight="8dp"
        app:recyclerPaddingTop="8dp"
        app:scrollbarStyle="insideOverlay"
        app:scrollbars="none" />
</LinearLayout>

使用rxjava和retrofit獲取json數據

我的數據來自 天性數據 ,只需要注冊即可獲得APIKEY。

數據請求核心代碼:

創建retrofit的請求接口

public interface ApiService{
    @GET("social/")
    Observable <NewsGson> getNewsData(@Query("key")String key,@Query("num") String num,@Query("page") int page);

注意返回的是Gson數據而且設置為"被觀察者"

數據獲取函數:

private void getData() {
        Log.d("page", page + "");
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("

                @Override
                public void onCompleted() {
                }

                @Override
                public void onError(Throwable e) {
                    Toast.makeText(getContext(),
                            "網絡連接失敗", Toast.LENGTH_LONG).show();
                }
            });
    page = page + 1;
}</code></pre> 

  1. 使用retrofit 發起網絡請求
  2. 數據通過rxjava提交先在io線程里,返回到主線程
  3. 中間設置map 轉換 把得到的Gson類轉化為所需的News類(可以省略這一步)
  4. subscribe的onNext里處理返回的最終數據。

關于建立Gson類

Gson是谷歌的Json處理包,添加依賴。

compile 'com.google.code.gson:gson:2.7'

配合插件:GsonFormat可以快速通過json數據建立對應類。

數據綁定到recyview

由于我們使用的是被擴展的recyview,所以用起來很方便。

具體使用去作者的githua EasyRecyclerView

  1. Adapter

    繼承recycle的adapter,主要返回自己的ViewHolder

    public class NewsAdapter extends RecyclerArrayAdapter<News> {
     public NewsAdapter(Context context) {
         super(context);
     }

    @Override public BaseViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) {

     return new NewsViewHolder(parent);
    

    } }</code></pre> </li>

  2. ViewHolder
  3. </ol>
    public class NewsViewHolder extends BaseViewHolder<News> {
      private TextView mTv_name;
        private ImageView mImg_face;
        private TextView mTv_sign;

    public NewsViewHolder(ViewGroup parent) {
        super(parent,R.layout.news_recycler_item);
        mTv_name = $(R.id.person_name);
        mTv_sign = $(R.id.person_sign);
        mImg_face = $(R.id.person_face);    }
    
    @Override
    public void setData(final News data) {
        mTv_name.setText(data.getTitle());
        mTv_sign.setText(data.getCtime());
        Glide.with(getContext())
                .load(data.getPicUrl())
                .placeholder(R.mipmap.ic_launcher)
                .centerCrop()
                .into(mImg_face);
    }
    
    
    

    }</code></pre>

    3.設置recycleview

    recyclerView.setAdapter(adapter = new NewsAdapter(getActivity()));
            recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        //添加邊框
        SpaceDecoration itemDecoration = new SpaceDecoration((int) PixUtil.convertDpToPixel(8, getContext()));
        itemDecoration.setPaddingEdgeSide(true);
        itemDecoration.setPaddingStart(true);
        itemDecoration.setPaddingHeaderFooter(false);
        recyclerView.addItemDecoration(itemDecoration);
    
        //更多加載
        adapter.setMore(R.layout.view_more, new RecyclerArrayAdapter.OnMoreListener() {
            @Override
            public void onMoreShow() {
                getData();
            }
    
            @Override
            public void onMoreClick() {
    
            }
        });
        //寫刷新事件
        recyclerView.setRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                recyclerView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        adapter.clear();
                        page = 0;
                        getData();
                    }
                }, 1000);
            }
        });
    
        //點擊事件
        adapter.setOnItemClickListener(new RecyclerArrayAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(int position) {
                ArrayList<String> data = new ArrayList<String>();
                data.add(adapter.getAllData().get(position).getPicUrl());
                data.add(adapter.getAllData().get(position).getUrl());
                Intent intent = new Intent(getActivity(), NewsDetailsActivity.class);
                //用Bundle攜帶數據
                Bundle bundle = new Bundle();
                bundle.putStringArrayList("data", data);
                intent.putExtras(bundle);
                startActivity(intent);
            }
        });</code></pre> 
    

    Glide網絡圖片加載庫

    一個專注于平滑圖片加載的庫:

    依賴:

    compile 'com.github.bumptech.glide:glide:3.7.0'

    基本使用:

    Glide.with(mContext)
                    .load(path)
                    .asGif()
                    .override(300,300)
                    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                    .placeholder(R.drawable.progressbar)
                    .thumbnail(1f)
                    .error(R.drawable.error)
                    .transform(new MyBitmapTransformation(mContext,10f))
                    .into(iv);

    新聞詳情頁

    布局:使用CoordinatorLayout實現上拉toolbar壓縮動畫。

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout xmlns:android="
    
    
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="256dp"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">
    
            <ImageView
                android:src="@mipmap/ic_launcher"
                android:id="@+id/ivImage"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:transitionName="新聞圖片"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7" />
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
    
    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
        <WebView
            android:id="@+id/web_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"></WebView>
    </android.support.v4.widget.NestedScrollView>
    

    </android.support.design.widget.CoordinatorLayout></code></pre>

    CoordinatorLayout+AppBarLayout里面配合CollapsingToolbarLayout布局技能實現toolbar的動畫:

    上面的Imgview加載圖片,下面的webview加載文章內容

    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_news_detail);

        toolbar.setTitle("新聞詳情");
    
        setSupportActionBar(toolbar);
    

    // 設置返回箭頭 getSupportActionBar().setDisplayHomeAsUpEnabled(true); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onBackPressed(); } }); //新頁面接收數據 Bundle bundle = this.getIntent().getExtras(); //接收name值 final ArrayList<String> data = bundle.getStringArrayList("data"); Log.d("url", data.get(0));

        webText.setWebViewClient(new WebViewClient() {
    
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // TODO Auto-generated method stub
                view.loadUrl(url);
                return true;
            }
        });
        webText.loadUrl(data.get(1));
    
        Glide.with(this)
                .load(data.get(0)).error(R.mipmap.ic_launcher)
                .fitCenter().into(ivImage);
    
    }</code></pre> 
    

    到這里基本完成:最后動態添加fragment

    //菜單事件添加
    if (id == R.id.nav_camera) {
                // Handle the camera action
                NewsFragment fragment=new NewsFragment();
                FragmentManager fragmentManager=getSupportFragmentManager();
                FragmentTransaction transaction=fragmentManager.beginTransaction();
                transaction.replace(R.id.fragment_container,fragment);
                transaction.commit();
    
            }

    效果測試:

    my.gif

    總結:

    只是勉強能用,還有很多細節沒有優化。接下來好要繼續學習。

    補充:關于ButterKnife的使用

    框架導入:

    搜索依賴butterknife導入:

    dependencies {
        compile fileTree(include: ['*.jar'], dir: 'libs')
        testCompile 'junit:junit:4.12'
        compile 'com.android.support:appcompat-v7:24.2.0'
        //依賴添加
        compile 'com.jakewharton:butterknife:8.4.0'
    }

    使用步驟:

    注意我這里寫的是8.40版本,和以前的有區別。

    如果的ButterKnife是8.01或者以上的話

    需要添加以下內容:

    1. classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.1.2'
            classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }

    2. apply plugin: 'com.neenbedankt.android-apt'

    apply plugin: 'com.android.application'
    apply plugin: 'com.neenbedankt.android-apt'

    3. apt 'com.jakewharton:butterknife-compiler:8.4.0'

    dependencies {
        compile fileTree(include: ['*.jar'], dir: 'libs')
        testCompile 'junit:junit:4.12'
        compile 'com.android.support:appcompat-v7:24.2.0'
        //依賴添加
        compile 'com.jakewharton:butterknife:8.4.0'
        apt 'com.jakewharton:butterknife-compiler:8.4.0'
    
    }

    Android Studio上方便使用butterknife注解框架的偷懶插件 Android Butterknife Zelezny :

    技巧:鼠標要移動到布局文件名上。

     

     

 本文由用戶 BaiCasner 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!