編輯:關於Android編程
今日頭條包含以下模塊:
首頁 視頻 天氣 和 我的
其中 首頁用於加載實時的新聞頻道及內容,可以實現點擊圖片查看圖片詳情,並且可以實現內容的收藏與取消收藏
視頻模塊暫時未加入任何內容
天氣模塊可以實現天氣的實時更新,最多可以顯示最近三天的天氣情況
我的 模塊中 點擊收藏,可以查看收藏的新聞內容
**Activity代碼:**
MainActivity
public class MainActivity extends AppCompatActivity { private FragmentTabHost ft; private String[] str = {"首頁", "視頻", "天氣", "我的"}; private int[] imgRes = {R.drawable.home, R.drawable.video, R.drawable.topic, R.drawable.my}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ft = (FragmentTabHost) findViewById(R.id.ft); getSupportActionBar().hide(); init(); } public void init() { //裝配 ft.setup(this, getSupportFragmentManager(), R.id.fl); Fragment home = new HomeFragment(); //TabSpec標簽說明 TabHost.TabSpec tabSpec0 = ft.newTabSpec(str[0]).setIndicator(getView(0)); ft.addTab(tabSpec0, home.getClass(), null); Fragment video = new VideoFragment(); TabHost.TabSpec tabSpec1 = ft.newTabSpec(str[1]).setIndicator(getView(1)); ft.addTab(tabSpec1, video.getClass(), null); Fragment topic = new TopicFragment(); TabHost.TabSpec tabSpec2 = ft.newTabSpec(str[2]).setIndicator(getView(2)); ft.addTab(tabSpec2, topic.getClass(), null); Fragment my = new MyFragment(); TabHost.TabSpec tabSpec3 = ft.newTabSpec(str[3]).setIndicator(getView(3)); ft.addTab(tabSpec3, my.getClass(), null); } public View getView(int i) { View v = getLayoutInflater().inflate(R.layout.tab_layout, null); ImageView iv = (ImageView) v.findViewById(R.id.iv); TextView tv = (TextView) v.findViewById(R.id.tv); iv.setImageResource(imgRes[i]); tv.setText(str[i]); return v; } }
ContentActivity
public class ContentActivity extends AppCompatActivity {
private WebView wv;
private ImageView back;
private TextView title, collection;
private boolean isExisits;
private NewsDao newsDao;
private String titles;
//全局變量自動賦值 局部變量不可以
private MyNews news;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_content); getSupportActionBar().hide(); wv = (WebView) findViewById(R.id.wv); back = (ImageView) findViewById(R.id.back); title = (TextView) findViewById(R.id.title); collection = (TextView) findViewById(R.id.collection); //getIntent()是將該項目中包含的原始intent檢索出來 //將檢索出來的intent賦值給一個Intent類型的變量intent Intent intent = getIntent(); String html = ""; titles = ""; if (intent != null) { news = intent.getParcelableExtra("news"); html = news.getHtml(); titles = news.getTitle(); } title.setText(titles); WebSettings ws = wv.getSettings(); //支持放大 ws.setSupportZoom(true); //顯示放大縮小的控件 一個加號一個減號 ws.setDisplayZoomControls(true); ws.setJavaScriptEnabled(true); ws.setDefaultTextEncodingName("utf-8"); //放大多少倍 //ws.setTextZoom(20); wv.loadDataWithBaseURL("", html, "text/html", "utf-8", ""); //設置內容的背景顏色 wv.setBackgroundColor(getResources().getColor(R.color.background)); newsDao = new NewsDao(this); //判斷新聞是否收藏過 checkNews(titles); back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); collection.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(isExisits){ newsDao.deleteNews(news.getTitle()); collection.setText("取消收藏"); }else { newsDao.addNews(news); collection.setText("收藏"); } checkNews(news.getTitle()); } }); } public void checkNews(String title) { MyNews myNews = newsDao.searchNews(title); // MyNews myNews = new MyNews(); if (myNews == null) { collection.setText("收藏"); isExisits = false; } else { collection.setText("取消收藏"); isExisits = true; } }
}
ImgActivity
public class ImgActivity extends AppCompatActivity { private PhotoViewPager pvp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_img); getSupportActionBar().hide(); pvp = (PhotoViewPager) findViewById(R.id.pvp); Intent intent = getIntent(); String imgUrls = intent.getStringExtra("img"); ListpvList = new ArrayList<>(); List imgList = paserImageList(imgUrls); for (int i = 0; i < imgList.size(); i++) { PhotoView pv = new PhotoView(this); pv.setScaleType(ImageView.ScaleType.CENTER_CROP); Glide.with(this).load(imgList.get(i)).into(pv); pvList.add(pv); } pvp.setAdapter(new MyViewPagerAdapter(pvList)); } public List paserImageList(String imgList) { List img = new ArrayList(); try { JSONArray ja = new JSONArray(imgList); for (int i = 0; i < ja.length(); i++) { JSONObject obj = (JSONObject) ja.get(i); if (obj.has("url")) { img.add(obj.getString("url")); } } } catch (JSONException e) { e.printStackTrace(); } return img; } public class MyViewPagerAdapter extends PagerAdapter { private List myData; public MyViewPagerAdapter(List myData) { this.myData = myData; } @Override public int getCount() { return myData.size(); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } //自己寫的 @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(myData.get(position)); return myData.get(position); } //自己寫的 @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(myData.get(position)); } } }
CollectionActivity
public class CollectionActivity extends AppCompatActivity { private ListView lv; private Listlist; private NewsDao newsDao; private NewsBaseAdapter na; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_collection); lv = (ListView) findViewById(R.id.lv); list = new ArrayList<>(); na = new NewsBaseAdapter(list, this); lv.setAdapter(na); newsDao = new NewsDao(this); getList(); } public void getList() { //先清空 避免疊加 list.clear(); //list=List不可用 由於不能觸發na.notifyDataSetChanged();所以導致布局加載不出數據來 list.addAll(newsDao.searchNews()); na.notifyDataSetChanged(); } @Override protected void onStart() { super.onStart(); getList(); } }
**adapter 代碼**
MyTabHostAdapter
public class MyTabHostAdapter extends FragmentPagerAdapter { private Listlist; public MyTabHostAdapter(FragmentManager fm, List list) { super(fm); this.list = list; } @Override public Fragment getItem(int position) { return list.get(position); } @Override public int getCount() { return list.size(); } }
NewsBaseAdapter
public class NewsBaseAdapter extends BaseAdapter { private ListmyNews; private Context context; //常量必須從0開始 並且不能跳著來不能0,2,4... private final int TYPE0 = 0; private final int TYPE1 = 1; private final int TYPE2 = 2; private final int TYPE3 = 3; public NewsBaseAdapter(List myNews, Context context) { this.myNews = myNews; this.context = context; } @Override public int getCount() { return myNews.size(); } @Override public Object getItem(int position) { return myNews.get(position); } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder vh; int type = getItemViewType(position); if (convertView == null) { vh = new ViewHolder(); if (type == 3) { convertView = LayoutInflater.from(context).inflate(R.layout.my_news_layout3, null); vh.title = (TextView) convertView.findViewById(R.id.title); vh.pubDate = (TextView) convertView.findViewById(R.id.pubDate); vh.source = (TextView) convertView.findViewById(R.id.source); vh.img = (ImageView) convertView.findViewById(R.id.img); vh.img2 = (ImageView) convertView.findViewById(R.id.img2); vh.img3 = (ImageView) convertView.findViewById(R.id.img3); vh.img.setOnClickListener(new ClickLisner(position)); vh.img2.setOnClickListener(new ClickLisner(position)); vh.img3.setOnClickListener(new ClickLisner(position)); convertView.setTag(vh); } else if (type == 2) { convertView = LayoutInflater.from(context).inflate(R.layout.my_news_layout2, null); vh.title = (TextView) convertView.findViewById(R.id.title); vh.pubDate = (TextView) convertView.findViewById(R.id.pubDate); vh.source = (TextView) convertView.findViewById(R.id.source); vh.img = (ImageView) convertView.findViewById(R.id.img); vh.img2 = (ImageView) convertView.findViewById(R.id.img2); vh.img.setOnClickListener(new ClickLisner(position)); vh.img2.setOnClickListener(new ClickLisner(position)); convertView.setTag(vh); } else if (type == 1) { convertView = LayoutInflater.from(context).inflate(R.layout.my_news_layout1, null); vh.title = (TextView) convertView.findViewById(R.id.title); vh.pubDate = (TextView) convertView.findViewById(R.id.pubDate); vh.source = (TextView) convertView.findViewById(R.id.source); vh.img = (ImageView) convertView.findViewById(R.id.img); vh.img.setOnClickListener(new ClickLisner(position)); convertView.setTag(vh); } else { convertView = LayoutInflater.from(context).inflate(R.layout.my_news_layout, null); vh.title = (TextView) convertView.findViewById(R.id.title); vh.pubDate = (TextView) convertView.findViewById(R.id.pubDate); vh.source = (TextView) convertView.findViewById(R.id.source); convertView.setTag(vh); } } else { vh = (ViewHolder) convertView.getTag(); } //通過這一句知道要加載哪個頻道的news MyNews news = myNews.get(position); if (type == 3) { vh.title.setText(news.getTitle()); vh.source.setText(news.getSource()); vh.pubDate.setText(news.getPubDate()); List list = paserImageList(news.getImageurls()); if (list.size() == 3) { Glide.with(context).load(list.get(0)).into(vh.img); Glide.with(context).load(list.get(1)).into(vh.img2); Glide.with(context).load(list.get(2)).into(vh.img3); } } else if (type == 2) { vh.title.setText(news.getTitle()); vh.source.setText(news.getSource()); vh.pubDate.setText(news.getPubDate()); List list = paserImageList(news.getImageurls()); if (list.size() == 2) { Glide.with(context).load(list.get(0)).into(vh.img); Glide.with(context).load(list.get(1)).into(vh.img2); } } else if (type == 1) { vh.title.setText(news.getTitle()); vh.source.setText(news.getSource()); vh.pubDate.setText(news.getPubDate()); List list = paserImageList(news.getImageurls()); if (list.size() == 1) { Glide.with(context).load(list.get(0)).into(vh.img); } } else { vh.title.setText(news.getTitle()); vh.source.setText(news.getSource()); vh.pubDate.setText(news.getPubDate()); } convertView.setOnClickListener(new ClickLisner(position)); return convertView; } public class ClickLisner implements View.OnClickListener { private int position; //在類裡生成構造 把position傳進來 public ClickLisner(int position) { this.position = position; } @Override public void onClick(View v) { int id=v.getId(); if(id==R.id.img||id==R.id.img2||id==R.id.img3){ Intent intent=new Intent(context, ImgActivity.class); intent.putExtra("img",myNews.get(position).getImageurls()); context.startActivity(intent); }else{ MyNews news = myNews.get(position); // Log.d("======", news.getHtml()); Intent intent = new Intent(context, ContentActivity.class); //MyNews要實現序列化 intent.putExtra("news", news); context.startActivity(intent); } } } public class ViewHolder { TextView pubDate; TextView title; ImageView img; TextView source; ImageView img2; ImageView img3; } @Override public int getItemViewType(int position) { List list = paserImageList(myNews.get(position).getImageurls()); if (list.size() == 3) { return TYPE3; } else if (list.size() == 1) { return TYPE1; } else if (list.size() == 2) { return TYPE2; } else { return TYPE0; } } @Override public int getViewTypeCount() { return 4; } public List paserImageList(String imgList) { List img = new ArrayList(); try { JSONArray ja = new JSONArray(imgList); for (int i = 0; i < imgList.length(); i++) { JSONObject obj = (JSONObject) ja.get(i); if (obj.has("url")) { img.add(obj.getString("url")); } } } catch (JSONException e) { e.printStackTrace(); } return img; } }
NewsFragmentAdapter
public class NewsFragmentAdapter extends FragmentPagerAdapter { private ListfragmentList; private List titles; public NewsFragmentAdapter(FragmentManager fm, List fragmentList, List titles) { //public NewsFragmentAdapter(List fm,FragmentActivity fragmentList) { super(fm); this.fragmentList = fragmentList; this.titles = titles; } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return fragmentList.size(); } @Override public CharSequence getPageTitle(int position) { return titles.get(position); } }
**dao文件**
NewsDao
public class NewsDao { private MyDbHelper myDbHelper; public NewsDao(Context context) { myDbHelper = new MyDbHelper(context); } //收藏新聞 public void addNews(MyNews myNews) { SQLiteDatabase db = myDbHelper.getWritableDatabase(); ContentValues cv = new ContentValues(); cv.put("title", myNews.getTitle()); cv.put("pubDate", myNews.getPubDate()); cv.put("source", myNews.getSource()); cv.put("html", myNews.getHtml()); cv.put("imageurls", myNews.getImageurls()); db.insert("news", null, cv); db.close(); } //查詢所有收藏 public List searchNews() { SQLiteDatabase db = myDbHelper.getReadableDatabase(); Cursor cs = db.query("news", null, null, null, null, null, null); MyNews myNews = null; Listlist = new ArrayList<>(); while (cs.moveToNext()) { myNews = new MyNews(); // cs.getColumnIndex("_id") id 這一列結果中的下標 myNews.setTitle(cs.getString(cs.getColumnIndex("title"))); myNews.setSource(cs.getString(cs.getColumnIndex("source"))); myNews.setPubDate(cs.getString(cs.getColumnIndex("pubDate"))); myNews.setHtml(cs.getString(cs.getColumnIndex("html"))); myNews.setImageurls(cs.getString(cs.getColumnIndex("imageurls"))); list.add(myNews); } cs.close(); db.close(); return list; } //查詢一條收藏 public MyNews searchNews(String title) { SQLiteDatabase db = myDbHelper.getWritableDatabase(); Cursor cs = db.query("news", null, "title = ? ", new String[]{title}, null, null, null); MyNews myNews = null; if (cs.moveToNext()) { myNews = new MyNews(); // cs.getColumnIndex("_id") id 這一列結果中的下標 myNews.setTitle(cs.getString(cs.getColumnIndex("title"))); myNews.setSource(cs.getString(cs.getColumnIndex("source"))); myNews.setPubDate(cs.getString(cs.getColumnIndex("pubDate"))); myNews.setHtml(cs.getString(cs.getColumnIndex("html"))); myNews.setImageurls(cs.getString(cs.getColumnIndex("imageurls"))); } cs.close(); db.close(); return myNews; } // 取消收藏 public void deleteNews(String title) { SQLiteDatabase db = myDbHelper.getWritableDatabase(); db.delete("news", "title= ? ", new String[]{title}); db.close(); } }
NewsCacheDao
public class NewsCacheDao { private Context context; private DaonewsDao; private DatabaseHelper helper; public NewsCacheDao(Context context) { this.context = context; helper = (DatabaseHelper) DatabaseHelper.getHelper(context); try { newsDao = helper.getDao(MyNews.class); } catch (SQLException e) { e.printStackTrace(); } } public void addNews(MyNews news) { try { //根據主鍵來判斷是更新還是修改 因此一定要有主鍵 newsDao.createOrUpdate(news); } catch (SQLException e) { e.printStackTrace(); } } //根據id查找新聞 public ArrayList searchNews(String chId) { try { return (ArrayList ) newsDao.queryBuilder().where().eq("channelId", chId).query(); } catch (SQLException e) { e.printStackTrace(); } return null; } }
WeatherCacheDao
public class WeatherCacheDao { private Context context; private DaoweatherDao; private DatabaseHelper helper; public WeatherCacheDao(Context context) { this.context = context; helper = (DatabaseHelper) DatabaseHelper.getHelper(context); try { weatherDao = helper.getDao(Weather.class); } catch (SQLException e) { e.printStackTrace(); } } public void addWeather(Weather weather) { try { //根據主鍵來判斷是更新還是修改 因此一定要有主鍵 weatherDao.createOrUpdate(weather); } catch (SQLException e) { e.printStackTrace(); } } //查詢所有 public List searchWeather() { try { return weatherDao.queryForAll(); } catch (SQLException e) { e.printStackTrace(); }return null; } public void deleteAll(){ try { weatherDao.deleteBuilder().delete(); } catch (SQLException e) { e.printStackTrace(); } } }
**dataBaseHelper文件**
DatabaseHelper
public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static final String TABLE_NAME = "ormtest.db"; private Mapdaos = new HashMap (); private static DatabaseHelper instance; private DatabaseHelper(Context context) { super(context, TABLE_NAME, null, 2); } @Override public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { try { TableUtils.createTable(connectionSource, MyNews.class); TableUtils.createTable(connectionSource, Weather.class); } catch (SQLException e) { e.printStackTrace(); } } @Override public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) { try { //匹配User.class類 TableUtils.dropTable(connectionSource, MyNews.class, true); TableUtils.dropTable(connectionSource, Weather.class, true); onCreate(database, connectionSource); } catch (SQLException e) { e.printStackTrace(); } } /** * 單例獲取該Helper * * @param context * @return */ public static synchronized DatabaseHelper getHelper(Context context) { context = context.getApplicationContext(); if (instance == null) { synchronized (DatabaseHelper.class) { if (instance == null) { instance = new DatabaseHelper(context); } } } return instance; } public synchronized Dao getDao(Class clazz) throws SQLException { Dao dao = null; String className = clazz.getSimpleName(); if (daos.containsKey(className)) { dao = daos.get(className); } if (dao == null) { dao = super.getDao(clazz); daos.put(className, dao); } return dao; } /** * 釋放資源 */ @Override public void close() { super.close(); for (String key : daos.keySet()) { Dao dao = daos.get(key); dao = null; } } }
MyDbHelper
public class MyDbHelper extends SQLiteOpenHelper { private final String DBNAME = "MyNews.db"; private final String TABLE_NAME = "news"; //在SQLite裡用作特殊標識的要加下劃線(主鍵) private final String INFO_COLUM_ID = "nid"; private final String INFO_COLUM_TITLE = "title"; private final String INFO_COLUM_HTML = "html"; private final String INFO_COLUM_PUBDATE = "pubDate"; private final String INFO_COLUM_SOURCE = "source"; private final String INFO_COLUM_IMG = "imageurls"; public MyDbHelper(Context context) { //版本號不能為0 super(context, "MyNews.db", null, 1); } public MyDbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { //如果沒有數據庫及數據表 就會在OnCreate裡自動創建 StringBuilder sql = new StringBuilder(); sql.append("Create table if not exists "); sql.append(TABLE_NAME + " ( "); // autoincrement 這一行自動增長 //sql.append(INFO_COLUM_ID + " varchar(50) primary key ,"); sql.append(INFO_COLUM_TITLE + " varchar(100) primary key ,"); sql.append(INFO_COLUM_HTML + " varchar(5000),"); sql.append(INFO_COLUM_PUBDATE + " varchar(20),"); sql.append(INFO_COLUM_SOURCE + " varchar(20),"); sql.append(INFO_COLUM_IMG + " varchar(500)"); sql.append(" ) "); //執行SQL db.execSQL(sql.toString()); } //數據庫更新升級 // 通過版本號Version 刪除以前的表 然後重新調用OnCreate @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //刪除表(delete是刪除表裡的數據) String sql = " drop table if exists " + TABLE_NAME; db.execSQL(sql); onCreate(db); } }
**entity文件**
MyNews
@DatabaseTable(tableName = "newsCache") public class MyNews implements Parcelable{ @DatabaseField private String pubDate; @DatabaseField(id=true) private String title; private String channelName; private String desc; @DatabaseField private String source; @DatabaseField private String channelId; private String link; @DatabaseField private String html; private ListallList; @DatabaseField private String imageurls; private String nid; public MyNews() { } protected MyNews(Parcel in) { pubDate = in.readString(); title = in.readString(); channelName = in.readString(); desc = in.readString(); source = in.readString(); channelId = in.readString(); link = in.readString(); html = in.readString(); allList = in.createStringArrayList(); imageurls = in.readString(); nid = in.readString(); } public static final Creator CREATOR = new Creator () { @Override public MyNews createFromParcel(Parcel in) { return new MyNews(in); } @Override public MyNews[] newArray(int size) { return new MyNews[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(pubDate); dest.writeString(title); dest.writeString(channelName); dest.writeString(desc); dest.writeString(source); dest.writeString(channelId); dest.writeString(link); dest.writeString(html); dest.writeStringList(allList); dest.writeString(imageurls); dest.writeString(nid); } public String getPubDate() { return pubDate; } public String getTitle() { return title; } public String getChannelName() { return channelName; } public String getDesc() { return desc; } public String getSource() { return source; } public String getChannelId() { return channelId; } public String getLink() { return link; } public String getHtml() { return html; } public List getAllList() { return allList; } public String getImageurls() { return imageurls; } public String getNid() { return nid; } public static Creator getCREATOR() { return CREATOR; } public void setPubDate(String pubDate) { this.pubDate = pubDate; } public void setTitle(String title) { this.title = title; } public void setChannelName(String channelName) { this.channelName = channelName; } public void setDesc(String desc) { this.desc = desc; } public void setSource(String source) { this.source = source; } public void setChannelId(String channelId) { this.channelId = channelId; } public void setLink(String link) { this.link = link; } public void setHtml(String html) { this.html = html; } public void setAllList(List allList) { this.allList = allList; } public void setImageurls(String imageurls) { this.imageurls = imageurls; } public void setNid(String nid) { this.nid = nid; } }
Weather
@DatabaseTable public class Weather implements Parcelable{ @DatabaseField(id=true) private String date; //日期 @DatabaseField private String text_day; //白天天氣現象文字 @DatabaseField private String code_day; //白天天氣現象代碼 @DatabaseField private String text_night; //晚間天氣現象文字 @DatabaseField private String code_night; //晚間天氣現象代碼 private String high; //當天最高溫度 private String low; //當天最低溫度 private String precip; //降水概率,范圍0~100,單位百分比 private String wind_direction; //風向文字 private String wind_direction_degree; //風向角度,范圍0~360 private String wind_speed; //風速,單位km/h(當unit=c時)、mph(當unit=f時) private String wind_scale; //風力等級 public Weather() { } protected Weather(Parcel in) { date = in.readString(); text_day = in.readString(); code_day = in.readString(); text_night = in.readString(); code_night = in.readString(); high = in.readString(); low = in.readString(); precip = in.readString(); wind_direction = in.readString(); wind_direction_degree = in.readString(); wind_speed = in.readString(); wind_scale = in.readString(); } public static final CreatorCREATOR = new Creator () { @Override public Weather createFromParcel(Parcel in) { return new Weather(in); } @Override public Weather[] newArray(int size) { return new Weather[size]; } }; public String getDate() { return date; } public String getText_day() { return text_day; } public String getCode_day() { return code_day; } public String getText_night() { return text_night; } public String getCode_night() { return code_night; } public String getHigh() { return high; } public String getLow() { return low; } public String getPrecip() { return precip; } public String getWind_direction() { return wind_direction; } public String getWind_direction_degree() { return wind_direction_degree; } public String getWind_speed() { return wind_speed; } public String getWind_scale() { return wind_scale; } public void setDate(String date) { this.date = date; } public void setText_day(String text_day) { this.text_day = text_day; } public void setCode_day(String code_day) { this.code_day = code_day; } public void setText_night(String text_night) { this.text_night = text_night; } public void setCode_night(String code_night) { this.code_night = code_night; } public void setHigh(String high) { this.high = high; } public void setLow(String low) { this.low = low; } public void setPrecip(String precip) { this.precip = precip; } public void setWind_direction(String wind_direction) { this.wind_direction = wind_direction; } public void setWind_direction_degree(String wind_direction_degree) { this.wind_direction_degree = wind_direction_degree; } public void setWind_speed(String wind_speed) { this.wind_speed = wind_speed; } public void setWind_scale(String wind_scale) { this.wind_scale = wind_scale; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(date); dest.writeString(text_day); dest.writeString(code_day); dest.writeString(text_night); dest.writeString(code_night); dest.writeString(high); dest.writeString(low); dest.writeString(precip); dest.writeString(wind_direction); dest.writeString(wind_direction_degree); dest.writeString(wind_speed); dest.writeString(wind_scale); } @Override public String toString() { return "Weather{" + "date='" + date + '\'' + ", text_day='" + text_day + '\'' + ", code_day='" + code_day + '\'' + ", text_night='" + text_night + '\'' + ", code_night='" + code_night + '\'' + ", high='" + high + '\'' + ", low='" + low + '\'' + ", precip='" + precip + '\'' + ", wind_direction='" + wind_direction + '\'' + ", wind_direction_degree='" + wind_direction_degree + '\'' + ", wind_speed='" + wind_speed + '\'' + ", wind_scale='" + wind_scale + '\'' + '}'; } }
**fragment文件**
HomeFragment
public class HomeFragment extends Fragment { private PagerSlidingTabStrip pst; private ViewPager vp; private ListfragmentList; private List
NewsFragment
public class NewsFragment extends Fragment { private PullToRefreshListView prlv; private NewsBaseAdapter nba; private ListnewsList; private NewsCacheDao newsCacheDao; private String url; private TextView tv; private int page = 1; private String id, name; //Handler要用OS包裡的 Handler的聲明方式不同 大括號後面要加分號 private Handler handler = new Handler() { //handleMessag在主線程中運行 相當於異步任務類裡的OnPostExcute() @Override public void handleMessage(Message msg) { super.handleMessage(msg); //判斷屬於哪個線程進行實現 if (msg.what == 1) { Bundle bundle = msg.getData(); List list = bundle.getParcelableArrayList("cache"); newsList.addAll(list); nba.notifyDataSetChanged(); //tv.setText("讀取緩存成功"); new GetNews().execute(url); } } }; public NewsFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_news, container, false); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); newsCacheDao = new NewsCacheDao(getActivity()); newsList = new ArrayList<>(); tv = (TextView) getView().findViewById(R.id.tv); prlv = (PullToRefreshListView) getView().findViewById(R.id.prlv); nba = new NewsBaseAdapter(newsList,getActivity()); prlv.setAdapter(nba); //設置上下都可以刷新 prlv.setMode(PullToRefreshBase.Mode.BOTH); //注冊監聽 prlv.setOnRefreshListener(new prlvLisen()); Bundle bundle = getArguments(); //接收HomeFragment中傳過來的數據 這樣才能知道現在處於哪個頻道下 然後根據頻道的id和name加載不同的數據 id = bundle.getString("id"); name = bundle.getString("name"); url = UrlUtil.newsUrl + "?channelId=" + id + "&channelName=" + name + "&needHtml=1"; //執行線程要用run //new GetCache(id).run(); new Thread(new GetCache()).start(); //getCache(id); //new GetNews().execute(url);(這一句轉去 getCache裡寫) } //讀取數據庫緩存 線程 public class GetCache implements Runnable { //run()在子線程中運行 @Override public void run() { Bundle bundle = new Bundle(); ArrayList list = newsCacheDao.searchNews(id); bundle.putParcelableArrayList("cache", list); //tv.setText("讀取緩存成功"); //nba.notifyDataSetChanged(); //new GetNews().execute(url); Message message = new Message(); //如果有需要的話先把數據放入bundle裡 再放入message裡 //message.setData(); message.setData(bundle); message.what = 1; //告訴它子線程已經執行完了 要返回子線程中去handler.sendMessage() handler.sendMessage(message); } } //加載網絡數據 異步任務類 public class GetNews extends AsyncTask { @Override protected String doInBackground(String... strings) { return HttpUtil.HttpGet(strings[0]); } @Override protected void onPostExecute(String s) { super.onPostExecute(s); //解析 新聞數據 try { JSONObject obj = new JSONObject(s); JSONObject body = obj.getJSONObject("showapi_res_body"); JSONObject pageBean = body.getJSONObject("pagebean"); JSONArray contentList = pageBean.getJSONArray("contentlist"); if (page == 1) { newsList.clear(); } //在獲取網絡的時候清空list(防止重復) 不是清空數據庫 for (int i = 0; i < contentList.length(); i++) { JSONObject jo = (JSONObject) contentList.get(i); //MyNews要有一個空的構造 不然這句話報錯 MyNews myNews = new MyNews(); myNews.setTitle(jo.getString("title")); myNews.setPubDate(jo.getString("pubDate")); myNews.setImageurls(jo.getString("imageurls")); myNews.setSource(jo.getString("source")); myNews.setHtml(jo.getString("html")); myNews.setChannelId(jo.getString("channelId")); newsCacheDao.addNews(myNews); newsList.add(myNews); } nba.notifyDataSetChanged(); prlv.onRefreshComplete(); } catch (JSONException e) { e.printStackTrace(); } } } // public void getCache(String id) { // //讀本地緩存 // newsList.addAll(newsCacheDao.searchNews(id)); // nba.notifyDataSetChanged(); // //如果沒有加載網絡 // if (newsList.size() == 0) { // new GetNews().execute(url); // } // } //下拉上拉 監聽 內部類 public class prlvLisen implements PullToRefreshBase.OnRefreshListener2 { @Override public void onPullDownToRefresh(PullToRefreshBase refreshView) { page = 1; url = UrlUtil.newsUrl + "?channelId=" + id + "&channelName=" + name + "&page=" + page + "&needHtml=1"; new GetNews().execute(url); } @Override public void onPullUpToRefresh(PullToRefreshBase refreshView) { page++; url = UrlUtil.newsUrl + "?channelId=" + id + "&channelName=" + name + "&page=" + page + "&needHtml=1"; new GetNews().execute(url); } }
MyFragment
public class MyFragment extends Fragment { private KenBurnsView img; private ImageView collection; public MyFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.my_layout, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); img= (KenBurnsView) getView().findViewById(R.id.img); collection= (ImageView) getView().findViewById(R.id.collection); collection.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getActivity(), CollectionActivity.class); startActivity(intent); } }); }
TopicFragment(裡面為天氣)
public class TopicFragment extends Fragment { private RequestQueue queue; private SwipeRefreshLayout swip; private CardView card1, card2, card3; private WeatherCacheDao weatherCacheDao; public TopicFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.weather_layout, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); card1 = (CardView) getView().findViewById(R.id.card1); card2 = (CardView) getView().findViewById(R.id.card2); card3 = (CardView) getView().findViewById(R.id.card3); weatherCacheDao = new WeatherCacheDao(getActivity()); queue = Volley.newRequestQueue(getActivity()); swip = (SwipeRefreshLayout) getView().findViewById(R.id.swip); //進度條背景色 swip.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.colorPrimary)); swip.setColorSchemeResources(R.color.colorAccent); swip.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override //下拉刷新時執行此方法 可以寫加載網絡。。。等命令 public void onRefresh() { //....... //收起刷新進度條 //swip.setRefreshing(false); //new Thread(new GetCache()).start(); getWeather(); } }); readDatabase(); } public void readDatabase() { Listlist = weatherCacheDao.searchWeather(); //去生成Weather的toString方法 paraseList(list); } //獲取天氣 public void getWeather() { String url = UrlUtil.weatherUrl + "?location=yantai"; StringGetRequest sgr = new StringGetRequest(Request.Method.GET, url, new Response.Listener () { @Override public void onResponse(String s) { if (!s.equals("")) { try { JSONObject obj = new JSONObject(s); JSONArray results = obj.getJSONArray("results"); JSONArray ja1 = ((JSONObject) (results.get(0))).getJSONArray("daily"); Gson gson = new Gson(); List list = gson.fromJson(ja1.toString(), new TypeToken >() { }.getType()); //只要一刷新就把緩存的清空掉 weatherCacheDao.deleteAll(); paraseList(list); // for (int i = 0; i < results.length(); i++) { // JSONObject jo = results.getJSONObject(i); // Weather weather = new Weather(); // weather.setDate(jo.getString("date")); // weather.setText_day(jo.getString("text_day")); // weather.setCode_day(jo.getString("code_day")); // weather.setText_night(jo.getString("text_night")); // weather.setCode_night(jo.getString("code_nigh")); // weather.setHigh(jo.getString("high")); // weather.setLow(jo.getString("low")); // weather.setPrecip(jo.getString("precip")); // weather.setWind_direction(jo.getString("wind_direction")); // weather.setWind_direction_degree(jo.getString("wind_direction_degree")); // weather.setWind_speed(jo.getString("wind_speed")); // weather.setWind_scale(jo.getString("wind_scale")); // weatherList.add(weather); // } } catch (JSONException e) { e.printStackTrace(); } } swip.setRefreshing(false); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { swip.setRefreshing(false); } }); sgr.putHeaders("apikey", "3f37b44e3115841957414d7c4bf6c0f5"); queue.add(sgr); } //解析weather public void paraseList(List
list) { for (int i = 0; i < list.size(); i++) { View view = LayoutInflater.from(getActivity()).inflate(R.layout.weather_content, null); Weather day = list.get(i); weatherCacheDao.addWeather(day); TextView date = (TextView) view.findViewById(R.id.date); TextView text_day = (TextView) view.findViewById(R.id.text_day); TextView code_day = (TextView) view.findViewById(R.id.code_day); TextView text_night = (TextView) view.findViewById(R.id.text_night); TextView code_night = (TextView) view.findViewById(R.id.code_night); TextView high = (TextView) view.findViewById(R.id.high); TextView low = (TextView) view.findViewById(R.id.low); TextView precip = (TextView) view.findViewById(R.id.precip); TextView wind_direction = (TextView) view.findViewById(R.id.wind_direction); TextView wind_direction_degree = (TextView) view.findViewById(R.id.wind_direction_degree); TextView wind_speed = (TextView) view.findViewById(R.id.wind_speed); TextView wind_scale = (TextView) view.findViewById(R.id.wind_scale); date.setText(day.getDate()); text_day.setText(day.getText_day()); code_day.setText(day.getCode_day()); text_night.setText(day.getText_night()); code_night.setText(day.getCode_night()); high.setText(day.getHigh()); low.setText(day.getLow()); precip.setText(day.getPrecip()); wind_direction.setText(day.getWind_direction()); wind_direction_degree.setText(day.getWind_direction_degree()); wind_scale.setText(day.getWind_scale()); wind_speed.setText(day.getWind_speed()); if (i == 0) { if (card1.getChildCount() > 0) { card1.removeAllViews(); } card1.addView(view); } if (i == 1) { if (card2.getChildCount() > 0) { card2.removeAllViews(); } card2.addView(view); } if (i == 2) { if (card3.getChildCount() > 0) { card3.removeAllViews(); } card3.addView(view); } } } }
**util工具類**
public class HttpUtil { public static String HttpGet(String uri){ HttpURLConnection con = null; BufferedReader reader = null; InputStream is = null; StringBuilder sbd = new StringBuilder(); try { URL url = new URL(uri); con = (HttpURLConnection) url.openConnection(); con.setConnectTimeout(5*1000); con.setReadTimeout(5*1000); con.setRequestProperty("apikey","5b46143955a4b1ff1b470a94315625cd"); con.connect(); if(con.getResponseCode()==200){ is = con.getInputStream(); reader = new BufferedReader(new InputStreamReader(is)); String strRead = null; while ((strRead = reader.readLine()) != null) { sbd.append(strRead); sbd.append("\r\n"); } return sbd.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if(reader!=null){ try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return ""; } }
public class FileUitlity { private static String ROOT_CACHE; private static FileUitlity instance = null; private FileUitlity() { } //創建文件夾 public static FileUitlity getInstance(Context context, String root_dir) { if (instance == null) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { ROOT_CACHE = (Environment.getExternalStorageDirectory() + "/" + root_dir + "/"); } else { ROOT_CACHE = (context.getFilesDir().getAbsolutePath() + "/" + root_dir + "/"); } File dir = new File(ROOT_CACHE); if (!dir.exists()) { dir.mkdirs(); } instance = new FileUitlity(); } return instance; } public File makeDir(String dir) { File fileDir = new File(ROOT_CACHE + dir); if (fileDir.exists()) { return fileDir; } else { fileDir.mkdirs(); return fileDir; } } //判斷文件是否存在SD卡 public static boolean fileExists(String fileName) { String state = Environment.getExternalStorageState(); if (!state.equals(Environment.MEDIA_MOUNTED)) { return false; } else { File root = Environment.getExternalStorageDirectory(); File file = new File(root, fileName); return file.exists(); } } //保存文件到SD卡 public static String saveFileToSdcard(String fileName, String content) { String state = Environment.getExternalStorageState(); if (!state.equals(Environment.MEDIA_MOUNTED)) { return "SD卡未就緒"; } File root = Environment.getExternalStorageDirectory(); FileOutputStream fos = null; try { fos = new FileOutputStream(root + "/" + fileName); fos.write(content.getBytes()); return "ok"; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } return ""; } //讀取SD卡文件 public static String readFileFromSdcard(String fileName) { String statue = Environment.getExternalStorageState(); if (!statue.equals(Environment.MEDIA_MOUNTED)) { return ""; } else { File root = Environment.getExternalStorageDirectory(); BufferedReader reader = null; FileInputStream fis = null; StringBuilder sbd = new StringBuilder(); try { fis = new FileInputStream(root + "/" + fileName); reader = new BufferedReader(new InputStreamReader(fis)); String row = ""; while ((row = reader.readLine()) != null) { sbd.append(row); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sbd.toString(); } } }
public class StringGetRequest extends StringRequest { private Mapheader; public StringGetRequest(int method, String url, Response.Listener listener, Response.ErrorListener errorListener) { super(method, url, listener, errorListener); header = new HashMap<>(); } public void putHeaders(String key, String value) { header.put(key, value); } public Map getHeaders() throws AuthFailureError { return header; } }
public class StringPostRequest extends StringRequest { private Mapparams; private Map header; public StringPostRequest(String url, Listener listener, ErrorListener errorListener) { //super實際調用了StringRequest的四參構造 super(Method.POST, url, listener, errorListener); params = new HashMap (); header = new HashMap (); } @Override //回調方法 用的時候往Map裡放值就可以 protected Map getParams() throws AuthFailureError { return params; } public void putParams(String key, String value) { this.params.put(key, value); } public Map getHeaders() throws AuthFailureError { return header; } public void putHeaders(String key, String value) { this.header.put(key, value); } }
public class UrlUtil { //獲取頻道的網絡接口 public static String channelUrl = "http://apis.baidu.com/showapi_open_bus/channel_news/channel_news"; /* /獲取頻道對應新聞的網絡接口 get請求參數: channelId :新聞頻道id,必須精確匹配 channelName :新聞頻道名稱,可模糊匹配 title :新聞標題,模糊匹配 page :頁數,默認1。每頁最多20條記 needContent:是否需要返回正文,1為需要 needHtml:是否需要返回正文的html格式,1為需要 */ //獲取新聞的網絡接口 public static String newsUrl = "http://apis.baidu.com/showapi_open_bus/channel_news/search_news"; /* 參數名 類型 必填 參數位置 描述 默認值 location string 是 urlParam 所查詢的位置 beijing language string 否 urlParam 語言 zh-Hans unit string 否 urlParam 單位 c start string 否 urlParam 起始時間 0 days string 否 urlParam 天數 3 */ //獲取天氣的網絡接口 public static String weatherUrl = "http://apis.baidu.com/thinkpage/weather_api/suggestion"; }
public class PhotoViewPager extends ViewPager { private float mTrans; private float mScale; /** * 最大的縮小比例 */ private static final float SCALE_MAX = 0.0f; /** * 保存position與對於的View */ private HashMapmChildrenViews = new LinkedHashMap (); /** * 滑動時左邊的元素 */ private View mLeft; /** * 滑動時右邊的元素 */ private View mRight; public PhotoViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // Log.e(TAG, "position=" + position+", positionOffset = "+positionOffset+" ,positionOffsetPixels = " + positionOffsetPixels+" , currentPos = " + getCurrentItem()); //滑動特別小的距離時,我們認為沒有動,可有可無的判斷 float effectOffset = isSmall(positionOffset) ? 0 : positionOffset; //獲取左邊的View mLeft = findViewFromObject(position); //獲取右邊的View mRight = findViewFromObject(position + 1); // 添加切換動畫效果 animateStack(mLeft, mRight, effectOffset, positionOffsetPixels); super.onPageScrolled(position, positionOffset, positionOffsetPixels); } public void setObjectForPosition(View view, int position) { mChildrenViews.put(position, view); } /** * 通過過位置獲得對應的View * * @param position * @return */ public View findViewFromObject(int position) { return mChildrenViews.get(position); } private boolean isSmall(float positionOffset) { return Math.abs(positionOffset) < 0.0001; } protected void animateStack(View left, View right, float effectOffset, int positionOffsetPixels) { if (right != null) { /** * 縮小比例 如果手指從右到左的滑動(切換到後一個):0.0~1.0,即從一半到最大 * 如果手指從左到右的滑動(切換到前一個):1.0~0,即從最大到一半 */ mScale = (1 - SCALE_MAX) * effectOffset + SCALE_MAX; /** * x偏移量: 如果手指從右到左的滑動(切換到後一個):0-720 如果手指從左到右的滑動(切換到前一個):720-0 */ mTrans = -getWidth() - getPageMargin() + positionOffsetPixels; right.setScaleX(mScale); right.setScaleY(mScale); right.setTranslationX(mTrans); } if (left != null) { left.bringToFront(); } } @Override public boolean onTouchEvent(MotionEvent ev) { try { return super.onTouchEvent(ev); } catch (IllegalArgumentException ex) { ex.printStackTrace(); } return false; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { try { return super.onInterceptTouchEvent(ev); } catch (IllegalArgumentException ex) { ex.printStackTrace(); } return false; } }
**布局文件**
<framelayout android:id="@+id/fl" android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent"> </framelayout>
<framelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"></framelayout>
運行效果展示:
顯示收藏的新聞:
想必大家都用過QQ的白板功能,裡面主要有兩項,一個是塗鴉功能,其實類似於上節的畫板功能,而另一個就是手寫,那記事本怎麼能沒有這個功能呢,今天就來為我們的記事本添加手寫功能
什麼是AppWidget?AppWidget就是我們平常在桌面上見到的那種一個個的小窗口,利用這個小窗口可以給用戶提供一些方便快捷的操作。本篇打算從以下幾個點來介紹App
今天在調ViewPager的時候,感覺ViewPager+Fragment這種做法更靈活,所以,現在拿出來Fragment再整理下。 一,為什麼要用
在為Fragment做切換動畫,啟動後遇到了一個異常: Caused by: java.lang.RuntimeException: Unknown animation