转载请注明出处:http://blog.csdn.net/amd123456789/article/details/52223353
一直想写一个与网络有交互的app来练练手,偶然发现知乎日报这个app,想着就着手模仿一个,尽管已经有人完全写了出来,但是自己不妨也写一个,全当练习。 这一篇就来写写引导页面,就是一张逐步放大的图片外加几个文本组成。效果图是这样(不会弄gif动态图):
首先,先搭好UI界面,很简单,两个TextView+一个ImageView, 布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/iv_guide" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" /> <TextView android:id="@+id/tv_guide" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="15dp" android:textColor="@android:color/darker_gray" android:textSize="15sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/tv_guide" android:layout_centerHorizontal="true" android:layout_margin="10dp" android:text="@string/app_name" android:textColor="@android:color/white" android:textSize="28sp" /> </RelativeLayout>其次,ImageView渐变放大效果的实现,用Animation。配好Animation 的xml文件, 在目录res/anim/guide_imageview_zoom.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">//表示放大后效果不重置 <scale android:duration="2000" android:fromXScale="1.0" android:fromYScale="1.0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:pivotX="50%" android:pivotY="50%" android:toXScale="1.2" android:toYScale="1.2" /> </set>Activity的主体逻辑,是从服务器获取资源,设置给布局上的控件。来看看这个activity的逻辑代码。
package com.example.seaice.zhihuribao; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.TextView; import com.example.seaice.zhihuribao.Utils.BaseApplication; import com.example.seaice.zhihuribao.Utils.ThreadMgr; import com.example.seaice.zhihuribao.Utils.UiUtils; import com.example.seaice.zhihuribao.bean.GuideInfo; import com.example.seaice.zhihuribao.protocol.GuideProtocol; import com.squareup.picasso.Picasso; import butterknife.ButterKnife; import butterknife.InjectView; public class MainActivity extends AppCompatActivity { private GuideProtocol guideProtocol;//负责从网络和本地获取数据 private GuideInfo guideInfo; @InjectView(R.id.iv_guide) ImageView iv_guide; @InjectView(R.id.tv_guide) TextView tv_guide; private Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.inject(this); guideProtocol = new GuideProtocol(); setImageGuide(); } //从服务器加载资源 private void loadDataFromProtocol(final Runnable r){ Runnable runnable = new Runnable() { @Override public void run() { guideInfo = guideProtocol.loadData();//获取数据 UiUtils.runOnUiThread(r); } }; ThreadMgr.getThreadPool().execute(runnable); } //设置imageview的放大效果 private void setImageGuide(){ Runnable r = new Runnable() { @Override public void run() { //guide image view Picasso.with(BaseApplication.getApplication()).load(guideInfo.getGuidePic()).into(iv_guide); Animation guideImageZoomAni = AnimationUtils.loadAnimation(MainActivity.this, R.anim.guide_imageview_zoom); iv_guide.startAnimation(guideImageZoomAni); tv_guide.setText(guideInfo.getGuideName()); } }; loadDataFromProtocol(r); } }GuideProtocol 是从网络/缓存获取json数据的一个封装类 1. 先从本地获取json数据 2. 如果为空,再从服务器上获取,并且保存到本地缓存 3. 若不为空,则直接解析json数据 以上便是这个类的主要逻辑,详细可以查看我之前的文章,三级缓存的基本原理 http://blog.csdn.net/amd123456789/article/details/52092927
package com.example.seaice.zhihuribao.protocol; import android.util.Log; import com.example.seaice.zhihuribao.Utils.FileUtils; import com.example.seaice.zhihuribao.Utils.HttpUtils; import com.example.seaice.zhihuribao.Utils.LogUtils; import com.example.seaice.zhihuribao.bean.GuideInfo; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import okhttp3.Request; import okhttp3.Response; /** * Created by seaice on 2016/8/11. */ public class GuideProtocol { private static final String GUIDE_URL = "http://news-at.zhihu.com/api/4/start-image/1080*1776"; private static final String GUIDE_DIR = "guide"; private static final String TAG = "GuideProtocol"; /** * 1.先从本地获取json数据 * 2.如果为空,再从服务器上获取 * 3.若获取到json,保存到本地 * 4.获取到json不为空,解析json数据 */ public GuideInfo loadData() { String json = loadDataFromLocal(); if (json == null) { Log.e(TAG, "从服务器获取"); json = loadDataFromServer(); if (json != null) { saveDataToLocal(json); } } else { Log.e(TAG, "已经从本地获取"); } if (json != null) { return paserJsonData(json); } return null; } private GuideInfo paserJsonData(String json) { try { JSONObject jsonObject = new JSONObject(json); String guideName = jsonObject.getString("text"); String guidePicUrl = jsonObject.getString("img"); GuideInfo guideInfo = new GuideInfo(guideName, guidePicUrl); Log.e(TAG, guideInfo.toString()); return guideInfo; } catch (JSONException e) { e.printStackTrace(); } return null; } //1.把整个json文件写到一个本地文件中 //2.把每条数据摘出来保存到数据库中 private String loadDataFromLocal() { File dir = FileUtils.getCacheDir(); File file = new File(dir, GUIDE_DIR); try { FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); long saveTime = Long.parseLong(br.readLine()); if (System.currentTimeMillis() > saveTime) { return null; } else { String str; StringWriter sw = new StringWriter(); while ((str = br.readLine()) != null) { sw.write(str); } LogUtils.i("本地获取数据"); return sw.toString(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private void saveDataToLocal(String json) { LogUtils.i("保存到本地"); //第一行写时间,然后保存起来 File dir = FileUtils.getCacheDir(); File file = new File(dir, GUIDE_DIR); BufferedWriter bw = null; try { FileWriter fw = new FileWriter(file); bw = new BufferedWriter(fw); bw.write(System.currentTimeMillis() + 1000 * 100 + ""); bw.newLine(); bw.write(json); bw.flush(); fw.close(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } private String loadDataFromServer() { String result = null; Request request = new Request.Builder().url(GUIDE_URL).build(); Response response = null; response = HttpUtils.execute(request); if (response != null && response.isSuccessful()) { try { result = response.body().string(); Log.e(TAG, result); return result; } catch (IOException e) { e.printStackTrace(); } } return null; } }于此对应的GuideInfo为:
package com.example.seaice.zhihuribao.bean; /** * Created by seaice on 2016/8/11. */ public class GuideInfo { public GuideInfo(String guideName, String guidePic) { this.guideName = guideName; this.guidePic = guidePic; } private String guideName; private String guidePic; public String getGuideName() { return guideName; } public void setGuideName(String guideName) { this.guideName = guideName; } public String getGuidePic() { return guidePic; } public void setGuidePic(String guidePic) { this.guidePic = guidePic; } @Override public String toString() { return "GuideInfo{" + "guideName='" + guideName + '\'' + ", guidePic=" + guidePic + '}'; } }