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); // 返回重试次数 } }); } }
程序中我已经加了比较清楚的注解,下面来看一下效果图,是不是图片已经出来了, 呵呵。。。忽略细节
好今天就到这里