Android用ニュースアプリの簡単な実装です。
1. レコードを更新する。
2021/11/14.
1. データソースapiを更新し、集計データニュースapiを使用するようにしました。
2. テキストビューグループをTabLayoutに置き換えた。
2021/11/13.
1. Fix the crash of dropdown refresh. 1. updated the api of data source
2. Add a new setting: if the dropdown doesn't get data within 5s, it will stop showing the loading bar.
------------------------------------------------------------------------------------------------------
2. まずエフェクト画像。
図1 図2
今回のアプリ開発に使用したapiの共有者が記事へのリンクを貼ってくれたことに感謝するとともに、必要な読者はこちらのリンクに移動してください。
リソース|NetEase News用APIを共有する - Jane's Book
集計データapiに差し替えました。 ニュースヘッドライン - ニュースヘッドライン API _APIデータインターフェース_APIインターフェース呼び出し_APIインターフェースプラットフォーム - 集計データ
3. 一般的な考え方の概要
アプリのインターフェイスは、図1、図2のようにシンプルです。図1の一番上はAndroidネイティブのタイトルバー、図2の一番上は私自身が定義したタイトルバーで、具体的なコードは後述します。図1のタイトルバーの下には5つのパネルを表すTextViewがあり、その下にはFragment+ViewPageのスライドページ、Fragmentの中にはRecyclerviewコントロールが入っています。RecyclerViewのアイテムをクリックすると、図2:使用したapiが対応するコンテンツ情報を返さなかったため、元のURLをWebViewで読み込む必要がありました。実は、画像と対応する情報をクロールするためにJsoupクローラのフレームワークも使ってみましたが、結果はあまり良くありません。それとも、私がJsoupの使い方があまり得意でないのかもしれませんね。
さて、アプリの全モジュールを説明しましたが、ここで各モジュールの詳細について説明します。
4.APPが使用するオープンソースライブラリ。
compile 'org.jsoup:jsoup:1.9.2'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.android.support:recyclerview-v7:24.2.1'
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.android.support:cardview-v7:24.2.1'
compile 'com.yalantis:phoenix:1.2.3'
compile 'com.android.support:support-v4:24.2.1'
フォニックス このエントリは、私が使用しているドロップダウン・リフレッシュ・オープンソース・コントロールです。
グライド 画像の効率的な読み込みのために。
カードビュー カードのレイアウトです。
okhttp Web通信フレームワーク。
レビュアー 言うまでもないことですが。
メインアクティビティ画面用のXMLファイルです。
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.thinkpad.wenews.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/finance"
android:layout_weight="1"
android:layout_width="0dp"
android:text="finance"
android:gravity="center_horizontal"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/movie"
android:layout_weight="1"
android:layout_width="0dp"
android:text="movie"
android:gravity="center"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/amusement"
android:layout_weight="1"
android:layout_width="0dp"
android:text="Entertainment"
android:gravity="center"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv"
android:layout_weight="1"
android:layout_width="0dp"
android:text="TV"
android:gravity="center"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/headline"
android:layout_weight="1"
android:layout_width="0dp"
android:text="headline"
android:gravity="center"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/newsLive"
android:layout_weight="1"
android:layout_width="0dp"
android:text="News"
android:gravity="center"
android:layout_height="wrap_content" />
</LinearLayout>
<com.yalantis.phoenix.PullToRefreshView
android:id="@+id/pull_to_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</com.yalantis.phoenix.PullToRefreshView>
</LinearLayout>
5. 本プロジェクトのポイント(ViewPager+フラグメント) 実装内容
今回のプロジェクトのキーポイントであるViewPager+fragmentパターンについて。
そこで、ViewPager+Fragmentを使って、上記のような今回のプロジェクトの機能を実現する方法を紹介します。
ビューページャー
ViewPagerは、実は私たちがよく知っているRecyclerViewと似ていて、アダプタ、オブジェクトを格納するListを必要とします。
ViewPagerの基本を学ぶためのリンク付き。 ViewPager詳細(I) --- 基本的な使い方_Android開発ノート - CSDNブログ_Androidのビューページャー
コード
package com.example.thinkpad.wenews;
import android.app.ProgressDialog;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.yalantis.phoenix.PullToRefreshView;
import java.util.ArrayList;
import java.util;
public class MainActivity extends AppCompatActivity {
ViewPager viewPager;
static List<TextView> tag;
List<Fragment> viewList;
static int tagPointer=0;
static ProgressDialog progressDialog ;
PullToRefreshView pullToRefreshView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressDialog=new ProgressDialog(MainActivity.this);
progressDialog.setMessage("Loading content... ");
viewPager = (ViewPager) findViewById(R.id.viewpager);
pullToRefreshView = (PullToRefreshView) findViewById(R.id.pull_to_refresh);
viewList = new ArrayList<Fragment>();// Load the View to be paged into the array
final amusementFragment fragment1 = new amusementFragment();
final financeFragment fragment2=new financeFragment();
final armyFragment fragment3=new armyFragment();
final headlineFragment fragment4=new headlineFragment();
final tvFragment fragment5=new tvFragment();
final newsFragment fragment6=new newsFragment();
viewList.add(fragment2);
viewList.add(fragment3);
viewList.add(fragment1);
viewList.add(fragment5);
viewList.add(fragment4);
viewList.add(fragment6);
FragmentManager fragmentManager=getSupportFragmentManager();
channelPager pagerAdapter=new channelPager(fragmentManager,viewList,this);
viewPager.setAdapter(pagerAdapter);
tag=new ArrayList<>();
tag.add((TextView)findViewById(R.id.finance));
tag.add((TextView)findViewById(R.id.movie));
tag.add((TextView)findViewById(R.id.amusement));
tag.add((TextView)findViewById(R.id.tv));
tag.add((TextView)findViewById(R.id.headline));
tag.add((TextView) findViewById(R.id.newsLive));
pullToRefreshView.setOnRefreshListener(new PullToRefreshView.OnRefreshListener() {
public void onRefresh() {
switch (tagPointer){
case 0:
GetNews(). fragment1;
break;
case 1:
fragment2.GetNews();
break;
case 2:
fragment3.GetNews();
break;
case 3:
fragment4.GetNews();
break;
case 4:
fragment5.GetNews();
break;
case 5:
Break;
}
pullToRefreshView.setRefreshing(false);
}
});
}
}
上記のようなコードで
channelPager pagerAdapter=new channelPager(fragmentManager,viewList,this); is creating my ViewPager adapter
その前に viewList.add(fragment2); を使って、いくつかのフラグメントオブジェクトを viewList に追加しています。
5.1 アダプタクラスchannelPagerからはじめましょう
package com.example.thinkpad.wenews;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util;
List; /**
* Created by thinkpad on 2019/3/3.
List; /* */
public class channelPager extends FragmentPagerAdapter {
List<Fragment> fragmentList=new ArrayList<>();
MainActivity mContext;
public channelPager(FragmentManager fm , List<Fragment> list,MainActivity mContext)
{
super(fm);
fragmentList=list;
this.mContext=mContext;
}
@Override
public Fragment getItem(int position) {
Log.d("getItem","good");
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList!= null ? fragmentList.size() : 0;
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
MainActivity.tagPointer=position;
switch (position) {
case 0: {
MainActivity.tag.get(0).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
List<TextView> others = new ArrayList<TextView>();
others.addAll(MainActivity.tag);
others.remove(0);
for (TextView textView : others) {
textView.setBackgroundColor(mContext.getResources().getColor(R.color.colorWhite));
}}
break;
case 1: {
MainActivity.tag.get(1).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
List<TextView> others = new ArrayList<TextView>();
others.addAll(MainActivity.tag);
others.remove(1);
for (TextView textView : others) {
textView.setBackgroundColor(mContext.getResources().getColor(R.color.colorWhite));
}
}
break;
case 2: {
MainActivity.tag.get(2).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
List<TextView> others = new ArrayList<TextView>();
others.addAll(MainActivity.tag);
others.remove(2);
for (TextView textView : others) {
textView.setBackgroundColor(mContext.getResources().getColor(R.color.colorWhite));
}
}
break;
case 3: {
MainActivity.tag.get(3).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
List<TextView> others = new ArrayList<TextView>();
others.addAll(MainActivity.tag);
others.remove(3);
for (TextView textView : others) {
textView.setBackgroundColor(mContext.getResources().getColor(R.color.colorWhite));
}
}
break;
case 4: {
MainActivity.tag.get(4).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
List<TextView
このクラスのコンストラクタは、FragmentManager, List<Fragment>, Mainacitivity の3つのパラメータを持っています。
最初の2つは、super()が親クラスのコンストラクタを呼び出してパラメータfmを渡していることも分かるので必須です。一方、List<Fragment>は言うまでもなく、このクラスでUIを操作する必要があるので、わざわざ渡すのはMainActivityのみとなります。コンストラクタの後には、2つのオーバーロード関数があり、1つ目は固定位置のフラグメントオブジェクトを返し、2つ目は数値を返します。
setPrimaryItemはフラグメントの現在位置を決定するメソッドで、このメソッドで該当部分のTextViewを水色にする機能を実現しています。詳しくはコードをご覧ください。
5.2 以下、フラグメント
package com.example.thinkpad.wenews;
import android.content;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class amusementFragment extends Fragment {
private List<NewItem> newItems=new ArrayList<NewItem>();
private RecyclerView recyclerView_amusement;
private NewsAdapter adapter;
public amusementFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.layout_amusement, container, false);
recyclerView_amusement=(RecyclerView) view.findViewById(R.id.recyclerview_amusement) ;
LinearLayoutManager layoutManager=new LinearLayoutManager(getContext());
recyclerView_amusement.setLayoutManager(layoutManager);
adapter=new NewsAdapter(newItems);
recyclerView_amusement.setAdapter(adapter);
GetNews();
return view;
}
public void GetNews(){
if(!MainActivity.progressDialog.isShowing()){
MainActivity.progressDialog.show();
}
HttpUtil.sendOkhttpRequest("https://3g.163.com/touch/reconstruct/article/list/BA10TA81wangning/0-20.html", new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("error11","Get error!!! ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("Success! ","12121212");
String text=response.body().string();
Log.d("response",text);
char test[]=text.toCharArray();
for(int i=0;i<9;i++)
test[i]=' ';
test[test.length-1]=' ';
Log.d("text",String.valueOf(test));
text=String.valueOf(test);
parseJSONWithJSONObject(text);
}
});
}
private void parseJSONWithJSONObject(String jsonData)
{
try{
Log.d("hello","hello");
JSONObject jsonObject=new JSONObject(jsonData);
Log.d("testtest",jsonObject.toString());
final JSONArray array=jsonObject.getJSONArray("BA10TA81wangning");
for(int i=1;i<array.length();i++)
{
NewItem one=new NewItem();
JSONObject object=array.getJSONObject(i);
one.setPictureAddress(object.getString("imgsrc"));
one.setTitle(object.getString("title"));
one.setContentAddress(object.getString("url"));
Log.d("contentadress",one.getContentAddress());
if(one.getContentAddress().toCharArray()[0]=='0')//filter the useless content address object into
{
Log.d("goodnull","truetrue!+");
continue;
}
Log.d("title12",one.getTitle());
Log.d("pic12",one.getPictureAddress());
boolean check=false;
for(NewItem c:newItems){
if(c.getTitle().equals(one.getTitle()){
check=true;
break;
}}
if(!check)
newItems.add(one);
}
Log.d("listsize","1234"+" " "+newItems.size());
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if(MainActivity.progressDialog.isShowing())
MainActivity.progressDialog.dismiss();
adapter.notifyDataSetChanged();
}
});
}catch (Exception e)
{
e.printStackTrace();
}
}
}
後で考えてもいいと思うんです。GetNews()は、私がコンテンツを更新するためのメソッドです。コンテンツをロードするための私のモジュールはonCreatView()に配置されているので、実際には、毎回フラグメントは、それが交差する前に更新されますが、これは非常に良い感じではない、あなたがより良い方法を持っている場合は、アドバイスを与えることを躊躇しないしてください。
httpsendrequestは、以下のようにリクエストを開始するメソッドです。
public class HttpUtil {
private String channel="";
private final static String apikey="LzQUsyWYuvT5kNqAAuUuY1pBmhhS37V7";
public static void sendOkhttpRequest(String address,okhttp3.Callback callback){
// Create RequestBody object to store the parameters to be submitted, the parameters are apikey,text,userid.
/*RequestBody requestBody=new FormBody.
.add("key",apikey)
.add("info",text)
.add("userid","128")
.build();*/
OkHttpClient client =new OkHttpClient();
Request request =new Request.
.url(address)
.build();
client.newCall(request).enqueue(callback);//enqueue method opens a sub-thread internally and eventually calls back the result to okhttp3.
}
}
5.3 RecyclerViewのアイテムクラスコード。
public class NewItem {
private String title;
private String pictureAddress;
private String contentAddress;
public String getContentAddress() {
return contentAddress;
}
public void setContentAddress(String contentAddress) {
this.contentAddress = contentAddress;
}
public String getPictureAddress() {
return pictureAddress;
}
public void setPictureAddress(String pictureAddress) {
this.pictureAddress = pictureAddress;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
6 概要とソースコードダウンロードリンク
基本的にはこれで終わりです。 ソースコードをダウンロードしている間に、「いいね!」やGitHubの「スター」を押していただけると幸いです。
githubプロジェクトのアドレスです。 https://github.com/DhyanaCoder/WeNews/tree/master ダウンロードだけでなく、自由に閲覧することができます。
関連
-
Androidでコンストラクタのインテントを解決できない原因と解決策
-
RecyclerViewです。アダプタが接続されていないため、レイアウトをスキップする
-
jniとjavaの間でbytearrayを受け渡しする
-
ログアウトしたエラー: java.lang.RuntimeException: アクティビティを開始できません ComponentInfo
-
selectionに主な型が含まれていないエラー
-
アプリケーションがメインスレで仕事をしすぎている可能性がある
-
Androidの内部育成に磨きをかける2年間
-
Android動的ブロードキャストの追加許可
-
Androidにおける縦の点線
-
SQLiteReadOnlyDatabaseException: 読み取り専用のデータベースを書き込もうとした (コード 1032)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Android Studio 3.1.2 新規プロジェクトのエラー AAPT2エラー:詳細はログを確認してください(Gradle 3.1.2)
-
第20章 OnCheckedChangeListenerイベント (ゼロから学ぶAndroid)
-
Androidで「デフォルトのアクティビティが見つからない」問題を解決する
-
Android StudioでJavaファイルが認識されない問題を解決(赤いJが表示される)。
-
AndroidでSPAN_EXCLUSIVE_EXCLUSIVEスパンが長さ0にできない場合、EditTextでコンテンツを削除する
-
Androidバージョン一覧
-
Androidレイアウトにおけるmargin,padding,alignの使い分けと違いについて
-
Android Studioの設定 Gradleの概要
-
Android TextViewの自動改行問題
-
android studioエミュレータの起動に失敗しました