swipebacklayout的使用,處理TextView中圖片的顯示以及類360滾動布局
來自: http://blog.csdn.net//chenguang79/article/details/50508629
今天我們來完成,點擊信息,進入到詳細的信息頁面。我們先根據下面的圖,來分析一下我們要如何布局,如何實現。

首先,我們看到,在這個詳細頁面的title中,文字是這個信息的標題,其中有一個共享按鈕的功能,可以將信息共享到其它程序中,還有一個更多,里面,有幾個功能,其中主要的就是修改文字的大小。下面,就是一個正常的信息顯示,大家注意,這個信息顯示有一個特點,就是在蘭色的title下面和作者信息之間的標題,如果,我向上推動信息,看下面更多的內容,你會發現,這個標題會向上移動,直到消息,然后,作者的信息這行,到了頂部就不動了,而下面的正文部分,開始滾動。
其次,我們看到下面的工具欄,你在向上移動正文的時候,他會隱藏,而向下的時候,它會再顯示出來。
接著,在正文的部分,會有圖片顯示出來,因為我采用的是將網上圖片下載到本地進行加載,為了不在模擬器中產生大量圖片,我就把這個功能關了,在本文的最后,我會將此功能打開,再切一個圖看一下。
最后,你會發現,我們各右滑動屏幕的時候,這個頁面各右移動,然后關掉。
好了,我們先從第一個問題開始解決,這個頁面的title不用多說了,就是采用我們原來的說過的Toolbar來處理,沒有什么可說的,唯一一點說明就是這個共享功能,這個系統給我們提供了一個現成的,只要加上應的樣式就會出來,可是這個圖標的大小,卻與別的圖標不一樣,大了很多,這個我一直沒有解決,哪位兄弟解決了,麻煩告訴我一下。
下面的布局,就有意思了,它有點像360里面的功能一樣,最上面的title會被隱藏,而中間的部分到了頂部就不動了,而正文會開始滾動,這個功能我想了很久,沒想到什么好的方法,后來看了網上幾位大神的blog才明白,這個只能是自定義布局開發。這里采用的是http://blog.csdn.net/lmj623565791/article/details/43649913此博客的代碼,只是簡單的改了一點,思路什么的,大家可以通過此博客去了解。
那么最后一個問題,就是下面的工具欄,會顯示和隱藏,我們會看到,它會在正文的上面顯示出來,這樣我們就采用一個FrameLayout做為主布局,然后把下面的工具欄放在上面,用程序來控制它的顯示與隱藏。好了,思路是這樣,我們開始代碼:
我們先把自定義布局的代碼寫出來,這個是根據上面我給出的blog代碼,簡單改了一點StickyNavLayout.java
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.OverScroller;
import android.widget.ScrollView;
import com.example.cg.zhihu_one.R;
/**
* Created by cg on 2015/8/18.
*/
public class StickyNavLayout extends LinearLayout {
private View mTop;
private View mNav;
private LinearLayout mViewPager;
private int mTopViewHeight;
private ViewGroup mInnerScrollView;
private boolean isTopHidden = false;
private OverScroller mScroller;
private VelocityTracker mVelocityTracker;
private int mTouchSlop;
private int mMaximumVelocity, mMinimumVelocity;
private float mLastY;
private boolean mDragging;
private boolean isInControl = false;
public StickyNavLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.VERTICAL);
mScroller = new OverScroller(context);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMaximumVelocity = ViewConfiguration.get(context)
.getScaledMaximumFlingVelocity();
mMinimumVelocity = ViewConfiguration.get(context)
.getScaledMinimumFlingVelocity();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTop = findViewById(R.id.id_stickynavlayout_topview);
mNav = findViewById(R.id.id_stickynavlayout_indicator);
View view = findViewById(R.id.id_stickynavlayout_viewpager);
if (!(view instanceof LinearLayout)) {
throw new RuntimeException(
"id_stickynavlayout_viewpager show used by ViewPager !");
}
mViewPager = (LinearLayout) view;
//此處直接給出下面的滾動條的布局
//mInnerScrollView = (ViewGroup)findViewById(R.id.scorl_main);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
params.height = getMeasuredHeight() - mNav.getMeasuredHeight();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mTopViewHeight = mTop.getMeasuredHeight();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getAction();
float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
float dy = y - mLastY;
getCurrentScrollView();
if (mInnerScrollView instanceof ScrollView) {
if (mInnerScrollView.getScrollY() == 0 && isTopHidden && dy > 0
&& !isInControl) {
isInControl = true;
ev.setAction(MotionEvent.ACTION_CANCEL);
MotionEvent ev2 = MotionEvent.obtain(ev);
dispatchTouchEvent(ev);
ev2.setAction(MotionEvent.ACTION_DOWN);
return dispatchTouchEvent(ev2);
}
} else if (mInnerScrollView instanceof ListView) {
ListView lv = (ListView) mInnerScrollView;
View c = lv.getChildAt(lv.getFirstVisiblePosition());
if (!isInControl && c != null && c.getTop() == 0 && isTopHidden
&& dy > 0) {
isInControl = true;
ev.setAction(MotionEvent.ACTION_CANCEL);
MotionEvent ev2 = MotionEvent.obtain(ev);
dispatchTouchEvent(ev);
ev2.setAction(MotionEvent.ACTION_DOWN);
return dispatchTouchEvent(ev2);
}
}
break;
}
return super.dispatchTouchEvent(ev);
}
/**
*
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
float dy = y - mLastY;
getCurrentScrollView();
if (Math.abs(dy) > mTouchSlop) {
mDragging = true;
if (mInnerScrollView instanceof ScrollView) {
// 如果topView沒有隱藏
// 或sc的scrollY = 0 && topView隱藏 && 下拉,則攔截
if (!isTopHidden
|| (mInnerScrollView.getScrollY() == 0
&& isTopHidden && dy > 0)) {
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
mLastY = y;
return true;
}
} else if (mInnerScrollView instanceof ListView) {
ListView lv = (ListView) mInnerScrollView;
View c = lv.getChildAt(lv.getFirstVisiblePosition());
// 如果topView沒有隱藏
// 或sc的listView在頂部 && topView隱藏 && 下拉,則攔截
if (!isTopHidden || //
(c != null //
&& c.getTop() == 0//
&& isTopHidden && dy > 0)) {
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
mLastY = y;
return true;
}
}
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mDragging = false;
recycleVelocityTracker();
break;
}
return super.onInterceptTouchEvent(ev);
}
private void getCurrentScrollView() {
//此處因為下面是滾動條,所以將viewpager隱掉
/*int currentItem = mViewPager.getCurrentItem();
PagerAdapter a = mViewPager.getAdapter();
if (a instanceof FragmentPagerAdapter) {
FragmentPagerAdapter fadapter = (FragmentPagerAdapter) a;
Fragment item = (Fragment) fadapter.instantiateItem(mViewPager,
currentItem);
mInnerScrollView = (ViewGroup) (item.getView()
.findViewById(R.id.id_stickynavlayout_innerscrollview));
} else if (a instanceof FragmentStatePagerAdapter) {
FragmentStatePagerAdapter fsAdapter = (FragmentStatePagerAdapter) a;
Fragment item = (Fragment) fsAdapter.instantiateItem(mViewPager,
currentItem);
mInnerScrollView = (ViewGroup) (item.getView()
.findViewById(R.id.id_stickynavlayout_innerscrollview));
}*/
}
@Override
public boolean onTouchEvent(MotionEvent event) {
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(event);
int action = event.getAction();
float y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished())
mScroller.abortAnimation();
mLastY = y;
return true;
case MotionEvent.ACTION_MOVE:
float dy = y - mLastY;
Log.e("TAG", "dy = " + dy + " , y = " + y + " , mLastY = " + mLastY);
if (!mDragging && Math.abs(dy) > mTouchSlop) {
mDragging = true;
}
if (mDragging) {
scrollBy(0, (int) -dy);
// 如果topView隱藏,且上滑動時,則改變當前事件為ACTION_DOWN
if (getScrollY() == mTopViewHeight && dy < 0) {
event.setAction(MotionEvent.ACTION_DOWN);
dispatchTouchEvent(event);
isInControl = false;
}
}
mLastY = y;
break;
case MotionEvent.ACTION_CANCEL:
mDragging = false;
recycleVelocityTracker();
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
break;
case MotionEvent.ACTION_UP:
mDragging = false;
mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocityY = (int) mVelocityTracker.getYVelocity();
if (Math.abs(velocityY) > mMinimumVelocity) {
fling(-velocityY);
}
recycleVelocityTracker();
break;
}
return super.onTouchEvent(event);
}
public void fling(int velocityY) {
mScroller.fling(0, getScrollY(), 0, velocityY, 0, 0, 0, mTopViewHeight);
invalidate();
}
@Override
public void scrollTo(int x, int y) {
if (y < 0) {
y = 0;
}
if (y > mTopViewHeight) {
y = mTopViewHeight;
}
if (y != getScrollY()) {
super.scrollTo(x, y);
}
isTopHidden = getScrollY() == mTopViewHeight;
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(0, mScroller.getCurrY());
invalidate();
}
}
private void initVelocityTrackerIfNotExists() {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
}
private void recycleVelocityTracker() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
} 好,我們來看一下主程序與布局
activity_index_detail.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<include
layout="@layout/toolbar" />
<com.example.cg. zhihu_one.untils.StickyNavLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@id/id_stickynavlayout_topview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#C1C1C1" >
<TextView
android:id="@+id/txt_index_detail_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
android:textColor="#454545"
android:textSize="@dimen/list_remark_size"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="2dp"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/id_stickynavlayout_indicator"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/netimg_index_detail_userpic"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:src="@drawable/img_empty_followers"
android:layout_marginTop="5dp"
android:layout_marginLeft="5dp"
android:layout_marginBottom="5dp"
/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="4">
<TextView
android:id="@+id/txt_index_detail_userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="@dimen/list_remark_size"
android:layout_marginTop="5dp"/>
<TextView
android:id="@+id/txt_index_detail_userRemark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/gray"
android:textSize="@dimen/list_remark_size"
android:layout_marginTop="2dp"
android:layout_marginBottom="5dp"
android:lines="1"/>
</LinearLayout>
<LinearLayout
android:id="@+id/linear_index_detail_zan"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="2"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:gravity="center"
android:clickable="true">
<View
android:layout_width="1dip"
android:layout_height="15dp"
android:background="@color/gray"
android:layout_gravity="center_vertical"
/>
<ImageView
android:id="@+id/img_index_detail_zan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_vote_normal"
android:layout_marginLeft="10dp"/>
<TextView
android:id="@+id/txt_index_detail_zanNum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="120"
android:layout_marginLeft="10dp"
android:textColor="@color/gray"/>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#CCCCCC" />
<LinearLayout
android:id="@id/id_stickynavlayout_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="2dp">
<ScrollView
android:id="@+id/scorl_main"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/txt_index_detail_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
/>
</ScrollView>
</LinearLayout>
</com.example.cg.zhihu_one.untils.StickyNavLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/linear_index_detail_seekbar"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:background="#D4D4D4"
android:layout_gravity="bottom"
android:gravity="center">
<TextView
android:text="@string/index_detail_TextSize_small"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"/>
<SeekBar
android:id="@+id/seekbar_index_detail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:max="5"
/>
<TextView
android:text="@string/index_detail_TextSize_big"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"/>
</LinearLayout>
<LinearLayout
android:id="@id/linear_index_detail_bottomtitle"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:background="#D4D4D4"
android:layout_gravity="bottom">
<TextView
android:id="@+id/txt_index_detail_help"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:text="@string/index_detail_help"
android:clickable="true"
android:gravity="center"
android:layout_marginTop="5dp"
android:drawableTop="@drawable/ic_nohelp"/>
<TextView
android:id="@+id/txt_index_detail_thank"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:layout_marginTop="5dp"
android:text="@string/index_detail_thank"
android:clickable="true"
android:gravity="center"
android:drawableTop="@drawable/ic_thank"/>
<TextView
android:id="@+id/txt_index_detail_Collection"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:layout_marginTop="5dp"
android:text="@string/index_detail_collection"
android:clickable="true"
android:gravity="center"
android:drawableTop="@drawable/ic_collect"/>
<TextView
android:id="@+id/txt_index_detail_Comment"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:layout_marginTop="5dp"
android:text="@string/index_detail_comment"
android:clickable="true"
android:gravity="center"
android:drawableTop="@drawable/ic_comment"/>
</LinearLayout>
</FrameLayout> 注意:這里在StickyNavLayout布局里,好幾個控件我們不是定義它的id,而是給它賦予id,這是為什么呢, 主要是為了自定義布局里面好取值,這里我們在values中定義了一個ids_sticky_nav_Llayout.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="id_stickynavlayout_topview" type="id"/>
<item name="id_stickynavlayout_viewpager" type="id"/>
<item name="id_stickynavlayout_indicator" type="id"/>
<item name="id_stickynavlayout_innerscrollview" type="id"/>
<item name="linear_index_detail_bottomtitle" type="id"/>
</resources>
當然了,為了以后改文字和通用性比較好, 我在values文件夾的strings.xml文件里,定義了一些文字
strings.xml
<resources>
<string name="app_name">zhihu_one</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="drawer_open">打開</string>
<string name="drawer_close">關閉</string>
<string name="menu_index">首頁</string>
<string name="menu_search">查詢</string>
<string name="menu_notify">通知</string>
<string name="menu_about">關于</string>
<string name="menu_register">登出</string>
<string name="menu_share">分享</string>
<string name="menu_shuffle">隨機看</string>
<string name="title_activity_index_detail">Index_detailActivity</string>
<string name="index_detail_TextSize_small">小</string>
<string name="index_detail_TextSize_big">大</string>
<string name="index_detail_help">沒有幫助</string>
<string name="index_detail_nohelp">撤消沒有幫助</string>
<string name="index_detail_thank">感謝</string>
<string name="index_detail_thanked">已感謝</string>
<string name="index_detail_collection">收藏</string>
<string name="index_detail_collectioned">已收藏</string>
<string name="index_detail_comment">評論 0</string>
</resources> 好,這時候,我們在原來的代碼中,Index_lv_Adapter.java中,將點擊事件中的跳轉的代碼加上,如下
listclass.linear_index_item_content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent cIntent = new Intent();
cIntent.setClass(context, Index_detailActivity.class);
cIntent.putExtra("questionID", list_index.get(position).getQuestionID());
cIntent.putExtra("questionTitle",list_index.get(position).getQuestionTitle());
context.startActivity(cIntent);
}
}); 這里有一點,你會問了,我傳一個id過去不就完了嗎,因為我的數據全是根據id,然后從服務器里傳回來的,為什么還要再專一個title呢。這個在后面,你就明白了。好了,我們來看Index_detailActivity.java的代碼。還記得我們的最后一個問題,就是向右滑動手機,這個Activity會向左移動然后關閉,這個呢,我們使用的是網上第三方插件,叫SwipeBackLayout,官方地址:https://github.com/ikew0ng/SwipeBackLayout。在我們android studio開發工具中,只要引入
compile 'me.imid.swipebacklayout.lib:library:1.0.0'即可。這里要注意一點啊。原生代碼繼承的是Activity可是我們這里使用了Toolbar哪么我們就得改寫一下,讓他繼承ActionBarActivity,我們重新建一個類叫SwipeBackToolBarActivity,代碼如下:
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import me.imid.swipebacklayout.lib.SwipeBackLayout;
import me.imid.swipebacklayout.lib.app.SwipeBackActivityBase;
import me.imid.swipebacklayout.lib.app.SwipeBackActivityHelper;
/**
* Created by cg on 2015/11/10.
*/
public class SwipeBackToolBarActivity extends ActionBarActivity implements SwipeBackActivityBase {
private SwipeBackActivityHelper mHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHelper = new SwipeBackActivityHelper(this);
mHelper.onActivityCreate();
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mHelper.onPostCreate();
}
@Override
public View findViewById(int id) {
View v = super.findViewById(id);
if (v == null && mHelper != null)
return mHelper.findViewById(id);
return v;
}
@Override
public SwipeBackLayout getSwipeBackLayout() {
return mHelper.getSwipeBackLayout();
}
@Override
public void setSwipeBackEnable(boolean enable) {
getSwipeBackLayout().setEnableGesture(enable);
}
@Override
public void scrollToFinishActivity() {
getSwipeBackLayout().scrollToFinishActivity();
}
}
我們先讓我們的主程序繼承這個類SwipeBackToolBarActivity。代碼如下:
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.android.volley.toolbox.NetworkImageView;
import com.example.cg.zhihu_one.untils.SwipeBackToolBarActivity;
import me.imid.swipebacklayout.lib.SwipeBackLayout;
public class Index_detailActivity extends SwipeBackToolBarActivity implements View.OnClickListener {
private SwipeBackLayout mSwipeBackLayout; //定義側滑退出此activity
private Toolbar toolbar; //定義toolbar
private int qid; //定義接到的問題id
private String questionTitle; //定義問題的標題
private ProgressDialog myProgressDialog; //定義信息等等控件
private TextView txt_index_detail_title; //定義問題的標題
private NetworkImageView netimg_index_detail_userpic; //定義用戶頭像
private TextView txt_index_detail_userName; //定義用戶名字
private TextView txt_index_detail_userRemark; //定義用戶簡介
private ImageView img_index_detail_zan; //定義點贊的圖標
private TextView txt_index_detail_zanNum; //定義點贊數
private ScrollView scorl_main; //內容滾動條
private TextView txt_index_detail_content; //定義內容
private LinearLayout linear_index_detail_bottomtitle; //定義底部工具欄
private LinearLayout id_stickynavlayout_indicator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index_detail);
qid = getIntent().getIntExtra("questionID", 0); //從列表頁,接收問題的id
questionTitle = getIntent().getStringExtra("questionTitle"); //接收到的標題
mSwipeBackLayout = getSwipeBackLayout();
int edgeFlag = SwipeBackLayout.EDGE_LEFT; //從右向左滑動
//int edgeFlag = SwipeBackLayout.EDGE_RIGHT; //從左向右滑動
//int edgeFlag = SwipeBackLayout.EDGE_BOTTOM; //從下向上滑動
//int edgeFlag = SwipeBackLayout.EDGE_ALL; //從右,右,下都可以滑動
mSwipeBackLayout.setEdgeTrackingEnabled(edgeFlag);
toolbar = (Toolbar)this.findViewById(R.id.toolbar);
toolbar.setTitle(questionTitle); // 標題的文字需在setSupportActionBar之前,不然會無效
setSupportActionBar(toolbar);
initControls();
}
/**
* 初始化各控件
*/
private void initControls() {
txt_index_detail_title = (TextView)findViewById(R.id.txt_index_detail_title);
//注意這里,我們把標題的內容給TextView賦值,是為了能讓我們自定義的StickNavLayout布局去算一下,它的高度。
//因為我們的數據值是通過異步從遠程服務器中得到了,如果現在不給值,會有一個時間差,會造成計算高度有誤
txt_index_detail_title.setText(questionTitle);
netimg_index_detail_userpic = (NetworkImageView)findViewById(R.id.netimg_index_detail_userpic);
txt_index_detail_userName = (TextView)findViewById(R.id.txt_index_detail_userName);
txt_index_detail_userRemark = (TextView)findViewById(R.id.txt_index_detail_userRemark);
txt_index_detail_zanNum = (TextView)findViewById(R.id.txt_index_detail_zanNum);
txt_index_detail_content = (TextView)findViewById(R.id.txt_index_detail_content);
txt_index_detail_content.setOnClickListener(this);
linear_index_detail_bottomtitle = (LinearLayout)findViewById(R.id.linear_index_detail_bottomtitle);
id_stickynavlayout_indicator = (LinearLayout)findViewById(R.id.id_stickynavlayout_indicator);
img_index_detail_zan = (ImageView)findViewById(R.id.img_index_detail_zan);
//linear_index_detail_seekbar = (LinearLayout) findViewById(R.id.linear_index_detail_seekbar);
//HideTextSizeAnimator(100);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_index_detail, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
}
} OK,我們來看一下效果,效果圖如下:

功能還不錯,Toolbar出來了,側滑也能關閉頁面了,可是為什么側滑出來背景是黑的啊。這就不好看了。背景應該是前一個頁面啊。這是因為我們雖然進行了側滑, 可是這個activity的背景是黑的,不是透明的,所以顯示不出來前一個頁面,我們只要把它的背景設置成透明就OK了,我們后面還要有幾個頁面使用這個效果,所以我們把 這個設置,放到style.xml文件中,我們來修改我們的style.xml文件.
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- toolbar(actionbar)顏色 -->
<item name="colorPrimary">@color/titleBlue</item>
<!-- 狀態欄顏色 -->
<item name="colorPrimaryDark">#3A5FCD</item>
<!--toolbar文字的顏色-->
<item name="@android:textColorPrimary">@android:color/white</item>
<!-- 窗口的背景顏色 -->
<item name="android:windowBackground">@android:color/white</item>
<!--toolbar上菜單文字的顏色-->
<item name="actionMenuTextColor">#ffffff</item>
</style>
<!--讓側滑頁面在側滑時,背景透明,讓AndroidManifest.xml文件的主樣式繼承它-->
<style name="AppTheme" parent="@style/AppBaseTheme">
<item name="android:windowIsTranslucent">true</item>
</style>
</resources> AndroidManifest.xml 文件的application中的android:theme的樣式修改為AppTheme。好讓我們看一下修改后的效果。

OK,側滑關掉頁面我們完成了,現在我們來從服務器讀取數據,給控件賦值,然后看一下我們中間的內容區是否和我們想的一樣。
為了得到頁面顯示的內容,我們先做一個class,做為models
goodAnswer.java
/**
* 內容頁顯示字段
* Created by cg on 2015/11/10.
*/
public class goodAnswer {
private int questionID; //問題id
private String questionTitle; //問題的標題
private int userID; //答題者的id
private String userName; //答題者姓名
private String userProfile; //答題者簡介
private String answerContent; //答題內容
private int aZambia; //答題被點選次數
private int ahelpId; //對自己是否有幫助
private int userCollectionId; //是否收藏
private String userPic; //用戶照片
private int answerNum; //回復數
private int userThank; //是否感謝
private int commentNum;
public goodAnswer() {
}
public goodAnswer(int questionID, String questionTitle, int userID, String userName, String userProfile, String answerContent, int aZambia, int ahelpId, int userCollectionId, String userPic, int answerNum, int userThank) {
this.questionID = questionID;
this.questionTitle = questionTitle;
this.userID = userID;
this.userName = userName;
this.userProfile = userProfile;
this.answerContent = answerContent;
this.aZambia = aZambia;
this.ahelpId = ahelpId;
this.userCollectionId = userCollectionId;
this.userPic = userPic;
this.answerNum = answerNum;
this.userThank = userThank;
}
public int getQuestionID() {
return questionID;
}
public void setQuestionID(int questionID) {
this.questionID = questionID;
}
public String getQuestionTitle() {
return questionTitle;
}
public void setQuestionTitle(String questionTitle) {
this.questionTitle = questionTitle;
}
public int getUserID() {
return userID;
}
public void setUserID(int userID) {
this.userID = userID;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserProfile() {
return userProfile;
}
public void setUserProfile(String userProfile) {
this.userProfile = userProfile;
}
public String getAnswerContent() {
return answerContent;
}
public void setAnswerContent(String answerContent) {
this.answerContent = answerContent;
}
public int getaZambia() {
return aZambia;
}
public void setaZambia(int aZambia) {
this.aZambia = aZambia;
}
public int getAhelpId() {
return ahelpId;
}
public void setAhelpId(int ahelpId) {
this.ahelpId = ahelpId;
}
public int getUserCollectionId() {
return userCollectionId;
}
public void setUserCollectionId(int userCollectionId) {
this.userCollectionId = userCollectionId;
}
public String getUserPic() {
return userPic;
}
public void setUserPic(String userPic) {
this.userPic = userPic;
}
public int getAnswerNum() {
return answerNum;
}
public void setAnswerNum(int answerNum) {
this.answerNum = answerNum;
}
public int getUserThank() {
return userThank;
}
public void setUserThank(int userThank) {
this.userThank = userThank;
}
} 好,我們來看一下Index_detailActivity.java的代碼
import android.app.ProgressDialog;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.ShareActionProvider;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.Volley;
import com.example.cg.zhihu_one.models.goodAnswer;
import com.example.cg.zhihu_one.untils.SwipeBackToolBarActivity;
import com.example.cg.zhihu_one.untils.configStatic;
import com.example.cg.zhihu_one.untils.imagesUntils;
import com.example.cg.zhihu_one.untils.webservicesUntils;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.BinaryHttpResponseHandler;
import org.apache.http.Header;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import me.imid.swipebacklayout.lib.SwipeBackLayout;
public class Index_detailActivity extends SwipeBackToolBarActivity implements View.OnClickListener {
private SwipeBackLayout mSwipeBackLayout; //定義側滑退出此activity
private Toolbar toolbar; //定義toolbar
private int qid; //定義接到的問題id
private String questionTitle; //定義問題的標題
private ProgressDialog myProgressDialog; //定義信息等等控件
private TextView txt_index_detail_title; //定義問題的標題
private NetworkImageView netimg_index_detail_userpic; //定義用戶頭像
private TextView txt_index_detail_userName; //定義用戶名字
private TextView txt_index_detail_userRemark; //定義用戶簡介
private ImageView img_index_detail_zan; //定義點贊的圖標
private TextView txt_index_detail_zanNum; //定義點贊數
private ScrollView scorl_main; //內容滾動條
private TextView txt_index_detail_content; //定義內容
private LinearLayout linear_index_detail_bottomtitle; //定義底部工具欄
private LinearLayout id_stickynavlayout_indicator;
private float oldy; //定義滾動scrollview的前一步滾動的值
private boolean isHideBottom = false; //是否隱藏底部工具欄
private TextView txt_index_detail_help; //定義底部工具欄,幫助
private boolean isHelp = false; //是否幫助,默認為否
private TextView txt_index_detail_thank; //定義底部工具欄,感謝
private boolean isThank = false; //是否感謝,默認為否
private TextView txt_index_detail_Collection; //定義底部工具欄,收藏
private boolean isCollection = false; //是否收藏,默認為否
private TextView txt_index_detail_Comment; //定義底部工具欄,評論
private boolean isComment = false; //是否評價,默認為否
private goodAnswer gAnswer; //定義最佳回答的類
//定義volley
private RequestQueue mQueue;
private ImageLoader imageLoader;
private String answerContent; //定義答案,主要是為了重新加載其中的圖片
//private PopupWindow popWin; //定義更多彈出對話框
private ShareActionProvider mShareActionProvider;
private LinearLayout linear_index_detail_zan; //點贊按鈕
private int isZan = 0; //是否點了贊同或是反對 0:未點 1:贊同 2:反對
private boolean isHideTextSize = true; //是否隱藏底部文字大小調整,默認是隱藏 true
private LinearLayout linear_index_detail_seekbar; //底部文字大小調整
private SeekBar seekbar_index_detail; //底部調整文字大小seebar
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index_detail);
qid = getIntent().getIntExtra("questionID", 0); //從列表頁,接收問題的id
questionTitle = getIntent().getStringExtra("questionTitle"); //接收到的標題
mSwipeBackLayout = getSwipeBackLayout();
int edgeFlag = SwipeBackLayout.EDGE_LEFT; //從右向左滑動
//int edgeFlag = SwipeBackLayout.EDGE_RIGHT; //從左向右滑動
//int edgeFlag = SwipeBackLayout.EDGE_BOTTOM; //從下向上滑動
//int edgeFlag = SwipeBackLayout.EDGE_ALL; //從右,右,下都可以滑動
mSwipeBackLayout.setEdgeTrackingEnabled(edgeFlag);
toolbar = (Toolbar)this.findViewById(R.id.toolbar);
toolbar.setTitle(questionTitle); // 標題的文字需在setSupportActionBar之前,不然會無效
setSupportActionBar(toolbar);
//初始化Volley,為用戶照片顯示
mQueue = Volley.newRequestQueue(this);
imageLoader = new ImageLoader(mQueue, new imagesUntils.BitmapCache() {
@Override
public Bitmap getBitmap(String s) {
return null;
}
@Override
public void putBitmap(String s, Bitmap bitmap) {
}
});
initControls();
initData(qid);
}
/**
* 初始化各控件
*/
private void initControls() {
txt_index_detail_title = (TextView)findViewById(R.id.txt_index_detail_title);
//注意這里,我們把標題的內容給TextView賦值,是為了能讓我們自定義的StickNavLayout布局去算一下,它的高度。
//因為我們的數據值是通過異步從遠程服務器中得到了,如果現在不給值,會有一個時間差,會造成計算高度有誤
txt_index_detail_title.setText(questionTitle);
netimg_index_detail_userpic = (NetworkImageView)findViewById(R.id.netimg_index_detail_userpic);
txt_index_detail_userName = (TextView)findViewById(R.id.txt_index_detail_userName);
txt_index_detail_userRemark = (TextView)findViewById(R.id.txt_index_detail_userRemark);
txt_index_detail_zanNum = (TextView)findViewById(R.id.txt_index_detail_zanNum);
txt_index_detail_content = (TextView)findViewById(R.id.txt_index_detail_content);
txt_index_detail_content.setOnClickListener(this);
linear_index_detail_bottomtitle = (LinearLayout)findViewById(R.id.linear_index_detail_bottomtitle);
id_stickynavlayout_indicator = (LinearLayout)findViewById(R.id.id_stickynavlayout_indicator);
img_index_detail_zan = (ImageView)findViewById(R.id.img_index_detail_zan);
//linear_index_detail_seekbar = (LinearLayout) findViewById(R.id.linear_index_detail_seekbar);
//HideTextSizeAnimator(100);
}
/**
* 初始化數據,根據問題id,取出相應的問題信息
* @param qid
*/
private void initData(final int qid) {
// 初始化數據和數據源
myProgressDialog = new ProgressDialog(this);
myProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); //設置風格為圓形進度條
myProgressDialog.setTitle("提示"); //設置標題
myProgressDialog.setMessage("數據加載中,請稍等..."); //設置內容
myProgressDialog.setIndeterminate(false); //設置進度是否為不明確
myProgressDialog.setCancelable(true); //設置進度條是否可以按退回鍵取消
myProgressDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try{
String soapObject = webservicesUntils.getIndexDetailgoodAnswer(qid);
if(soapObject!="0") {
try {
gAnswer = new goodAnswer();
//操作單條json數據
JSONObject jsonAnswer = new JSONObject(soapObject);
gAnswer.setQuestionID(jsonAnswer.getInt("questionID"));
gAnswer.setQuestionTitle(jsonAnswer.getString("questionTitle"));
gAnswer.setUserID(jsonAnswer.getInt("userID"));
gAnswer.setUserName(jsonAnswer.getString("userName"));
gAnswer.setUserProfile(jsonAnswer.getString("userProfile"));
gAnswer.setAnswerContent(jsonAnswer.getString("answerContent"));
gAnswer.setaZambia(jsonAnswer.getInt("aZambia"));
gAnswer.setAhelpId(jsonAnswer.getInt("ahelpId"));
gAnswer.setUserCollectionId(jsonAnswer.getInt("userCollectionId"));
gAnswer.setUserPic(jsonAnswer.getString("userPic"));
gAnswer.setAnswerNum(jsonAnswer.getInt("answerNum"));
gAnswer.setUserThank(jsonAnswer.getInt("userThank"));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
msg.arg1 = 1;
msg.obj = gAnswer;
handler.sendMessage(msg);
}catch (Exception ex){
msg.arg1 = 2;
}
}
}).start();
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.arg1==1)
{
toolbar.setTitle(gAnswer.getQuestionTitle()); // 標題的文字需在setSupportActionBar之前,不然會無效
setSupportActionBar(toolbar);
//actionBar.setTitle(gAnswer.getQuestionTitle()); //為actionbar設置標題
txt_index_detail_title.setText(gAnswer.getQuestionTitle()); //為標題賦值
//為圖片控件加載圖片,采用NetworkImageView控件。
//第一項是加載圖片控件的默認圖片,一般是圖片加載中,這樣的圖片
//第二項是當發生錯誤的時候加載的圖片,如網絡圖片路徑不對或是加載失敗的時候顯示的圖片
//第三項就是加載網絡圖片了
netimg_index_detail_userpic.setDefaultImageResId(R.drawable.img_empty_followers);
netimg_index_detail_userpic.setErrorImageResId(R.drawable.img_empty_followers);
netimg_index_detail_userpic.setImageUrl(gAnswer.getUserPic(), imageLoader);
txt_index_detail_userName.setText(gAnswer.getUserName()); //為用戶名賦值
txt_index_detail_userRemark.setText(gAnswer.getUserProfile()); //用戶簡介
txt_index_detail_zanNum.setText(gAnswer.getaZambia() + ""); //點贊數
answerContent = gAnswer.getAnswerContent();
//txt_index_detail_Comment.setText("評論 " + gAnswer.getAnswerNum()); //評論數
//txt_index_detail_content.setText(answerContent);
//從系統設置中,讀取默認的字體大小
SharedPreferences preferences = getSharedPreferences(configStatic.SHAREDPREFERENCES_NAME, MODE_PRIVATE);
int contentTextSize = preferences.getInt("contentTextSize", 14);
txt_index_detail_content.setTextSize(contentTextSize);
//seekbar_index_detail.setProgress((contentTextSize - 10) / 2);
txt_index_detail_content.setText(Html.fromHtml(answerContent, imageGetter, null));
/*if(gAnswer.getAhelpId()!=0)
{
txt_index_detail_help.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.ic_nohelped), null, null);
txt_index_detail_help.setText(R.string.index_detail_nohelp);
isHelp = true;
}
if(gAnswer.getUserThank()!=0)
{
txt_index_detail_thank.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.ic_thanked), null, null);
txt_index_detail_thank.setText(R.string.index_detail_thanked);
}
if(gAnswer.getUserCollectionId()!=0)
{
txt_index_detail_Collection.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.ic_collected), null, null);
txt_index_detail_Collection.setText(R.string.index_detail_collectioned);
isCollection = true;
}
HideTextSizeAnimator(100);*/
}else
{
Toast.makeText(Index_detailActivity.this, "數據加載失敗!", Toast.LENGTH_LONG).show();
}
myProgressDialog.dismiss();
}
};
/**
* 處理 TextView中的圖片,對圖片地址進行處理
*/
Html.ImageGetter imageGetter = new Html.ImageGetter(){
@Override
public Drawable getDrawable(String source) {
Drawable drawable=null;
/**
* 判斷圖片是本地圖片還是網絡圖片,如果是本地圖片,直接調用,如果是網絡圖片,先下載再調用
* */
if(source.indexOf("http://")!=-1) {
//showPic(source);
}else
{
drawable=Drawable.createFromPath(source);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
}
return drawable;
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_index_detail, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
}
/**
* TextView中加載圖片的處理,主要是根據文本中圖片的地址,把網絡上的圖片下到手機中,以方便讀取
* @param url
*/
private void showPic(final String url) {
AsyncHttpClient client = new AsyncHttpClient();
// 指定文件類型
String[] allowedContentTypes = new String[]{"image/png", "image/jpeg"};
// 獲取二進制數據如圖片和其他文件
client.get(url, new BinaryHttpResponseHandler(allowedContentTypes) {
@Override
public void onSuccess(int statusCode, Header[] headers,
byte[] binaryData) {
String tempPath = Environment.getExternalStorageDirectory()
.getPath() + "/" + new Date().getTime() + ".jpg";
// TODO Auto-generated method stub
// 下載成功后需要做的工作
//progress.setProgress(0);
//
Log.e("binaryData:", "共下載了:" + binaryData.length);
//
Bitmap bmp = BitmapFactory.decodeByteArray(binaryData, 0,
binaryData.length);
File file = new File(tempPath);
// 壓縮格式
Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
// 壓縮比例
int quality = 100;
try {
// 若存在則刪除
if (file.exists())
file.delete();
// 創建文件
file.createNewFile();
//
OutputStream stream = new FileOutputStream(file);
// 壓縮輸出
bmp.compress(format, quality, stream);
// 關閉
stream.close();
//
//Toast.makeText(MainActivity.this, "下載成功\n" + tempPath,
//Toast.LENGTH_LONG).show();
Log.e("url", url);
Log.e("tempPath", tempPath);
//此處是當圖片已經下到本地之后,再根據本地地址重新加載一次文字內容,這樣圖片就加載到了TextView中
//這里一直沒有想到更好的方法
answerContent = answerContent.replace(url, tempPath);
txt_index_detail_content.setText(Html.fromHtml(answerContent, imageGetter, null));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers,
byte[] binaryData, Throwable error) {
// TODO Auto-generated method stub
Toast.makeText(Index_detailActivity.this, "下載失敗", Toast.LENGTH_LONG).show();
}
public void onProgress(int bytesWritten, int totalSize) {
// TODO Auto-generated method stub
super.onProgress(bytesWritten, totalSize);
int count = (int) ((bytesWritten * 1.0 / totalSize) * 100);
// 下載進度顯示
//progress.setProgress(count);
Log.e("下載 Progress>>>>>", bytesWritten + " / " + totalSize);
}
@Override
public void onRetry(int retryNo) {
// TODO Auto-generated method stub
super.onRetry(retryNo);
// 返回重試次數
}
});
}
} 知識點:
1,因為知乎這個程序是分app和web兩個版本的,很多問題都是在web端輸入的,所以它app內容部分,正常是用webview調html的代碼實現的,在這里我只是為了簡化,就直接使用了TextView。這里我們使用Html.fromHtml方法來加載內容,可以解析一部分html代碼,但不是全部的,比較表格 table它就不認。所以這里的內容我就做了點簡單的樣式,就是回車。我們要知道和學習的就是Html.fromHtml
2,正文中的圖片下載,我們使用的是第三方插件,android-async-http。它的官網是https://github.com/loopj/android-async-http。我們在android studio中只要引入compile 'com.loopj.android:android-async-http:1.4.8'即可。
好,我們看一下代碼
import android.app.ProgressDialog;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.ShareActionProvider;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.Volley;
import com.example.cg.zhihu_one.models.goodAnswer;
import com.example.cg.zhihu_one.untils.SwipeBackToolBarActivity;
import com.example.cg.zhihu_one.untils.configStatic;
import com.example.cg.zhihu_one.untils.imagesUntils;
import com.example.cg.zhihu_one.untils.webservicesUntils;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.BinaryHttpResponseHandler;
import org.apache.http.Header;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import me.imid.swipebacklayout.lib.SwipeBackLayout;
public class Index_detailActivity extends SwipeBackToolBarActivity implements View.OnClickListener {
private SwipeBackLayout mSwipeBackLayout; //定義側滑退出此activity
private Toolbar toolbar; //定義toolbar
private int qid; //定義接到的問題id
private String questionTitle; //定義問題的標題
private ProgressDialog myProgressDialog; //定義信息等等控件
private TextView txt_index_detail_title; //定義問題的標題
private NetworkImageView netimg_index_detail_userpic; //定義用戶頭像
private TextView txt_index_detail_userName; //定義用戶名字
private TextView txt_index_detail_userRemark; //定義用戶簡介
private ImageView img_index_detail_zan; //定義點贊的圖標
private TextView txt_index_detail_zanNum; //定義點贊數
private ScrollView scorl_main; //內容滾動條
private TextView txt_index_detail_content; //定義內容
private LinearLayout linear_index_detail_bottomtitle; //定義底部工具欄
private LinearLayout id_stickynavlayout_indicator;
private float oldy; //定義滾動scrollview的前一步滾動的值
private boolean isHideBottom = false; //是否隱藏底部工具欄
private TextView txt_index_detail_help; //定義底部工具欄,幫助
private boolean isHelp = false; //是否幫助,默認為否
private TextView txt_index_detail_thank; //定義底部工具欄,感謝
private boolean isThank = false; //是否感謝,默認為否
private TextView txt_index_detail_Collection; //定義底部工具欄,收藏
private boolean isCollection = false; //是否收藏,默認為否
private TextView txt_index_detail_Comment; //定義底部工具欄,評論
private boolean isComment = false; //是否評價,默認為否
private goodAnswer gAnswer; //定義最佳回答的類
//定義volley
private RequestQueue mQueue;
private ImageLoader imageLoader;
private String answerContent; //定義答案,主要是為了重新加載其中的圖片
//private PopupWindow popWin; //定義更多彈出對話框
private ShareActionProvider mShareActionProvider;
private LinearLayout linear_index_detail_zan; //點贊按鈕
private int isZan = 0; //是否點了贊同或是反對 0:未點 1:贊同 2:反對
private boolean isHideTextSize = true; //是否隱藏底部文字大小調整,默認是隱藏 true
private LinearLayout linear_index_detail_seekbar; //底部文字大小調整
private SeekBar seekbar_index_detail; //底部調整文字大小seebar
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index_detail);
qid = getIntent().getIntExtra("questionID", 0); //從列表頁,接收問題的id
questionTitle = getIntent().getStringExtra("questionTitle"); //接收到的標題
mSwipeBackLayout = getSwipeBackLayout();
int edgeFlag = SwipeBackLayout.EDGE_LEFT; //從右向左滑動
//int edgeFlag = SwipeBackLayout.EDGE_RIGHT; //從左向右滑動
//int edgeFlag = SwipeBackLayout.EDGE_BOTTOM; //從下向上滑動
//int edgeFlag = SwipeBackLayout.EDGE_ALL; //從右,右,下都可以滑動
mSwipeBackLayout.setEdgeTrackingEnabled(edgeFlag);
toolbar = (Toolbar)this.findViewById(R.id.toolbar);
toolbar.setTitle(questionTitle); // 標題的文字需在setSupportActionBar之前,不然會無效
setSupportActionBar(toolbar);
//初始化Volley,為用戶照片顯示
mQueue = Volley.newRequestQueue(this);
imageLoader = new ImageLoader(mQueue, new imagesUntils.BitmapCache() {
@Override
public Bitmap getBitmap(String s) {
return null;
}
@Override
public void putBitmap(String s, Bitmap bitmap) {
}
});
initControls();
initData(qid);
}
/**
* 初始化各控件
*/
private void initControls() {
txt_index_detail_title = (TextView)findViewById(R.id.txt_index_detail_title);
//注意這里,我們把標題的內容給TextView賦值,是為了能讓我們自定義的StickNavLayout布局去算一下,它的高度。
//因為我們的數據值是通過異步從遠程服務器中得到了,如果現在不給值,會有一個時間差,會造成計算高度有誤
txt_index_detail_title.setText(questionTitle);
netimg_index_detail_userpic = (NetworkImageView)findViewById(R.id.netimg_index_detail_userpic);
txt_index_detail_userName = (TextView)findViewById(R.id.txt_index_detail_userName);
txt_index_detail_userRemark = (TextView)findViewById(R.id.txt_index_detail_userRemark);
txt_index_detail_zanNum = (TextView)findViewById(R.id.txt_index_detail_zanNum);
txt_index_detail_content = (TextView)findViewById(R.id.txt_index_detail_content);
txt_index_detail_content.setOnClickListener(this);
linear_index_detail_bottomtitle = (LinearLayout)findViewById(R.id.linear_index_detail_bottomtitle);
id_stickynavlayout_indicator = (LinearLayout)findViewById(R.id.id_stickynavlayout_indicator);
img_index_detail_zan = (ImageView)findViewById(R.id.img_index_detail_zan);
//linear_index_detail_seekbar = (LinearLayout) findViewById(R.id.linear_index_detail_seekbar);
//HideTextSizeAnimator(100);
}
/**
* 初始化數據,根據問題id,取出相應的問題信息
* @param qid
*/
private void initData(final int qid) {
// 初始化數據和數據源
myProgressDialog = new ProgressDialog(this);
myProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); //設置風格為圓形進度條
myProgressDialog.setTitle("提示"); //設置標題
myProgressDialog.setMessage("數據加載中,請稍等..."); //設置內容
myProgressDialog.setIndeterminate(false); //設置進度是否為不明確
myProgressDialog.setCancelable(true); //設置進度條是否可以按退回鍵取消
myProgressDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try{
String soapObject = webservicesUntils.getIndexDetailgoodAnswer(qid);
if(soapObject!="0") {
try {
gAnswer = new goodAnswer();
//操作單條json數據
JSONObject jsonAnswer = new JSONObject(soapObject);
gAnswer.setQuestionID(jsonAnswer.getInt("questionID"));
gAnswer.setQuestionTitle(jsonAnswer.getString("questionTitle"));
gAnswer.setUserID(jsonAnswer.getInt("userID"));
gAnswer.setUserName(jsonAnswer.getString("userName"));
gAnswer.setUserProfile(jsonAnswer.getString("userProfile"));
gAnswer.setAnswerContent(jsonAnswer.getString("answerContent"));
gAnswer.setaZambia(jsonAnswer.getInt("aZambia"));
gAnswer.setAhelpId(jsonAnswer.getInt("ahelpId"));
gAnswer.setUserCollectionId(jsonAnswer.getInt("userCollectionId"));
gAnswer.setUserPic(jsonAnswer.getString("userPic"));
gAnswer.setAnswerNum(jsonAnswer.getInt("answerNum"));
gAnswer.setUserThank(jsonAnswer.getInt("userThank"));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
msg.arg1 = 1;
msg.obj = gAnswer;
handler.sendMessage(msg);
}catch (Exception ex){
msg.arg1 = 2;
}
}
}).start();
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.arg1==1)
{
toolbar.setTitle(gAnswer.getQuestionTitle()); // 標題的文字需在setSupportActionBar之前,不然會無效
setSupportActionBar(toolbar);
//actionBar.setTitle(gAnswer.getQuestionTitle()); //為actionbar設置標題
txt_index_detail_title.setText(gAnswer.getQuestionTitle()); //為標題賦值
//為圖片控件加載圖片,采用NetworkImageView控件。
//第一項是加載圖片控件的默認圖片,一般是圖片加載中,這樣的圖片
//第二項是當發生錯誤的時候加載的圖片,如網絡圖片路徑不對或是加載失敗的時候顯示的圖片
//第三項就是加載網絡圖片了
netimg_index_detail_userpic.setDefaultImageResId(R.drawable.img_empty_followers);
netimg_index_detail_userpic.setErrorImageResId(R.drawable.img_empty_followers);
netimg_index_detail_userpic.setImageUrl(gAnswer.getUserPic(), imageLoader);
txt_index_detail_userName.setText(gAnswer.getUserName()); //為用戶名賦值
txt_index_detail_userRemark.setText(gAnswer.getUserProfile()); //用戶簡介
txt_index_detail_zanNum.setText(gAnswer.getaZambia() + ""); //點贊數
answerContent = gAnswer.getAnswerContent();
//txt_index_detail_Comment.setText("評論 " + gAnswer.getAnswerNum()); //評論數
//txt_index_detail_content.setText(answerContent);
//從系統設置中,讀取默認的字體大小
SharedPreferences preferences = getSharedPreferences(configStatic.SHAREDPREFERENCES_NAME, MODE_PRIVATE);
int contentTextSize = preferences.getInt("contentTextSize", 14);
txt_index_detail_content.setTextSize(contentTextSize);
//seekbar_index_detail.setProgress((contentTextSize - 10) / 2);
txt_index_detail_content.setText(Html.fromHtml(answerContent, imageGetter, null));
/*if(gAnswer.getAhelpId()!=0)
{
txt_index_detail_help.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.ic_nohelped), null, null);
txt_index_detail_help.setText(R.string.index_detail_nohelp);
isHelp = true;
}
if(gAnswer.getUserThank()!=0)
{
txt_index_detail_thank.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.ic_thanked), null, null);
txt_index_detail_thank.setText(R.string.index_detail_thanked);
}
if(gAnswer.getUserCollectionId()!=0)
{
txt_index_detail_Collection.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.ic_collected), null, null);
txt_index_detail_Collection.setText(R.string.index_detail_collectioned);
isCollection = true;
}
HideTextSizeAnimator(100);*/
}else
{
Toast.makeText(Index_detailActivity.this, "數據加載失敗!", Toast.LENGTH_LONG).show();
}
myProgressDialog.dismiss();
}
};
/**
* 處理 TextView中的圖片,對圖片地址進行處理
*/
Html.ImageGetter imageGetter = new Html.ImageGetter(){
@Override
public Drawable getDrawable(String source) {
Drawable drawable=null;
/**
* 判斷圖片是本地圖片還是網絡圖片,如果是本地圖片,直接調用,如果是網絡圖片,先下載再調用
* */
if(source.indexOf("http://")!=-1) {
showPic(source);
}else
{
drawable=Drawable.createFromPath(source);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
}
return drawable;
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_index_detail, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
}
/**
* TextView中加載圖片的處理,主要是根據文本中圖片的地址,把網絡上的圖片下到手機中,以方便讀取
* @param url
*/
private void showPic(final String url) {
AsyncHttpClient client = new AsyncHttpClient();
// 指定文件類型
String[] allowedContentTypes = new String[]{"image/png", "image/jpeg"};
// 獲取二進制數據如圖片和其他文件
client.get(url, new BinaryHttpResponseHandler(allowedContentTypes) {
@Override
public void onSuccess(int statusCode, Header[] headers,
byte[] binaryData) {
String tempPath = Environment.getExternalStorageDirectory()
.getPath() + "/" + new Date().getTime() + ".jpg";
// TODO Auto-generated method stub
// 下載成功后需要做的工作
//progress.setProgress(0);
//
Log.e("binaryData:", "共下載了:" + binaryData.length);
//
Bitmap bmp = BitmapFactory.decodeByteArray(binaryData, 0,
binaryData.length);
File file = new File(tempPath);
// 壓縮格式
Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
// 壓縮比例
int quality = 100;
try {
// 若存在則刪除
if (file.exists())
file.delete();
// 創建文件
file.createNewFile();
//
OutputStream stream = new FileOutputStream(file);
// 壓縮輸出
bmp.compress(format, quality, stream);
// 關閉
stream.close();
//
//Toast.makeText(MainActivity.this, "下載成功\n" + tempPath,
//Toast.LENGTH_LONG).show();
Log.e("url", url);
Log.e("tempPath", tempPath);
//此處是當圖片已經下到本地之后,再根據本地地址重新加載一次文字內容,這樣圖片就加載到了TextView中
//這里一直沒有想到更好的方法
answerContent = answerContent.replace(url, tempPath);
txt_index_detail_content.setText(Html.fromHtml(answerContent, imageGetter, null));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers,
byte[] binaryData, Throwable error) {
// TODO Auto-generated method stub
Toast.makeText(Index_detailActivity.this, "下載失敗", Toast.LENGTH_LONG).show();
}
public void onProgress(int bytesWritten, int totalSize) {
// TODO Auto-generated method stub
super.onProgress(bytesWritten, totalSize);
int count = (int) ((bytesWritten * 1.0 / totalSize) * 100);
// 下載進度顯示
//progress.setProgress(count);
Log.e("下載 Progress>>>>>", bytesWritten + " / " + totalSize);
}
@Override
public void onRetry(int retryNo) {
// TODO Auto-generated method stub
super.onRetry(retryNo);
// 返回重試次數
}
});
}
} 程序中我已經加了比較清楚的注解,下面來看一下效果圖,是不是圖片已經出來了, 呵呵。。。忽略細節

好今天就到這里