1. 程式人生 > >android開發實現微博正文效果、頂部懸浮、ScrollView巢狀ListView

android開發實現微博正文效果、頂部懸浮、ScrollView巢狀ListView

先來看一下效果圖
這裡寫圖片描述
從圖中不難看出,我這裡使用了ScrollView巢狀ListView的方式來實現的這種效果。
這裡我們需要重寫一下ScrollView,程式碼如下:

package com.gsssk.ddpolice.myview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;

/**
 * Created by Administrator on 2016/6/15.
 */
public class MyScrollView extends ScrollView { //回撥介面的物件 private OnScrollListener onScrollListener; public MyScrollView(Context context) { super(context); } public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public MyScrollView
(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent ev) { return super.onTouchEvent(ev); } /**在滑動的時候呼叫我們自己寫的回撥方法,來獲取滑動距離*/ @Override protected void onScrollChanged
(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if(onScrollListener!=null){ onScrollListener.onScroll(t); } } /**滑動回撥監聽的介面*/ public interface OnScrollListener{ /**回撥方法,返回MyScrollView在Y軸方向的滑動距離*/ public void onScroll(int scrollY); } public OnScrollListener getOnScrollListener() { return onScrollListener; public void setOnScrollListener(OnScrollListener onScrollListener) { this.onScrollListener = onScrollListener; } }

這裡MyScrollView繼承了ScrollView,並重寫了onScrollChanged()方法,這個方法在ScrollView滑動的過程中不斷被呼叫,通過我們寫的介面中的回撥方法來獲取滑動的距離。

int ViewGroupTop;
@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            ////獲得ll_ViewGroup1_LRDA的頂部
            viewGroupTop = ll_Location1_LifeRewardDetail.getBottom();
        }
    }

如圖評論和分享的所在的LinearLayout,通過這個方法來得到它的頂部位置。
在下面的java程式碼中評論和分享的所在的LinearLayout的id=ll_Top_LifeRewardDetail
評論和分享的所在的LinearLayout的父佈局叫ll_ViewGroup2_LRDA也是一個LinearLayout。
想實現懸浮效果在頂部需要給它留一個父佈局LinearLayout,
id=ll_ViewGroup2_LRDA。平常的時候他是隱藏的,需要的時候他是顯現的。

msv_ScrollView_LRDA.setOnScrollListener(this);

//監聽滾動Y值變化,通過addView和removeView來實現懸停效果
    @Override
    public void onScroll(int scrollY) {
    //如果滑動的距離大於分享評論所在的位置
        if (scrollY >= viewGroupTop) {
        //如果分享評論不在頂部的父佈局中
            if (ll_Top_LifeRewardDetail.getParent() != ll_ViewGroup2_LRDA) {
           //讓頂部父佈局顯示出來     
           ll_ViewGroup2_LRDA.setVisibility(View.VISIBLE);
           //讓listView獲得焦點     
           lv_Share_LifeRewardDetail.setFocusable(true);
           lv_Comment_LifeRewardDetail.setFocusable(true);
            //把分享和評論從原始的父佈局中移除 
            ll_ViewGroup1_LRDA.removeView(ll_Top_LifeRewardDetail);
            //把分享評論加入頂部的佈局中
            ll_ViewGroup2_LRDA.addView(ll_Top_LifeRewardDetail);
            }
        } //如果滑動距離小於分享評論所在的位置
        else if (ll_Top_LifeRewardDetail.getParent() != ll_ViewGroup1_LRDA) {
            ll_ViewGroup2_LRDA.setVisibility(View.GONE);
            lv_Share_LifeRewardDetail.setFocusable(false);
            lv_Comment_LifeRewardDetail.setFocusable(false);
            ll_ViewGroup2_LRDA.removeView(ll_Top_LifeRewardDetail);
            ll_ViewGroup1_LRDA.addView(ll_Top_LifeRewardDetail);
        }
    }

通過上述程式碼可以看出,實現頂部懸浮效果分為四部步:

1.確定要懸浮的佈局(這裡是分享評論)、給懸浮佈局一個不在懸浮狀態時的父佈局、給懸浮佈局一個頂部懸浮時的父佈局。
2.確定分享評論佈局的頂部位置(要懸浮的佈局)
3.獲取ScrollView滑動的距離。
4.通過滑動距離與分享評論頂部位置的比較,來進行往父佈局中移除新增的操作(要先移除在新增)。

這樣就實現了懸浮的效果,但是通常在ScrollView中使用ListView就會出現ListView只顯示一行的問題。通過下面方法可以給ListView一個剛好顯示全部內容的高度。

    public class Utility {  
        public static void setListViewHeightBasedOnChildren(ListView listView) {  
            //獲取ListView的Adapter
            ListAdapter listAdapter = listView.getAdapter();   
            if (listAdapter == null) {  
                // pre-condition  
                return;  
            }  

            int totalHeight = 0;  
            for (int i = 0; i < listAdapter.getCount(); i++) {  
                View listItem = listAdapter.getView(i, null, listView);  
                listItem.measure(0, 0);
                //獲取ListView所以Item高度之和。  
                totalHeight += listItem.getMeasuredHeight();  
            }  

            ViewGroup.LayoutParams params = listView.getLayoutParams();  
            params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));  
        // listView.getDividerHeight()獲取子項間分隔符佔用的高度   
        // params.height最後得到整個ListView完整顯示需要的高度 
            listView.setLayoutParams(params);  
        }  
    }  

然後在呼叫這個方法,引數是相應的ListView物件

ScrollViewSetListViewHeight.setListViewHeightBasedOnChildren(lv_Share_LifeRewardDetail);