2011-01-12 51 views
0

我想創建一個類,可以添加到佈局文件,具有適配器集,然後從DataSetObserver更新。充氣視圖並將它們添加到Horizo​​ntalScrollView內的LinearLayout - 奇數行爲

在Nexus One上,這似乎一般工作正常,但在G1上我有一些奇怪的行爲。

所以該活動的佈局文件是:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" android:layout_width="fill_parent" 
android:layout_height="fill_parent"> 

<include android:layout_width="fill_parent" 
    android:layout_height="wrap_content" android:id="@+id/ActionBarInclude" 
    layout="@layout/action_bar"></include> 

    <LinearLayout android:layout_width="fill_parent" 
    android:layout_height="fill_parent" android:orientation="vertical" 
    android:background="@drawable/action_bar_drop_shadow"> 

    <TextView android:layout_height="wrap_content" 
    android:layout_width="fill_parent" android:gravity="center" 
    android:id="@+id/AccountSummaryAppTitleTextView" android:text="" 
    style="@style/titleTextView"></TextView> 

    <co.uk.gauntface.android.admob.views.TabBarScrollView 
    android:id="@+id/AccountSummaryTabBarScrollView" 
    android:layout_width="fill_parent" android:layout_height="wrap_content" 
    android:scrollbars="none"> 

    </co.uk.gauntface.android.admob.views.TabBarScrollView> 

    <co.uk.gauntface.android.admob.views.SlidingLayout android:layout_width="fill_parent" 
    android:id="@+id/AccountSummarySlidingLayout" android:layout_weight="1" 
    android:layout_height="wrap_content" android:scrollbars="none" android:fadingEdge="none" 
    android:fillViewport="true"> 
      </co.uk.gauntface.android.admob.views.SlidingLayout> 

    </LinearLayout> 

</LinearLayout> 

現在我已經設置FillViewPort到真正的原因是因爲類似的問題在這裏:LinearLayout not expanding inside a ScrollView 雖然這並沒有固定我的問題。

爲活動的源代碼是:

package co.uk.gauntface.android.admob; 

import java.util.ArrayList; 
import co.uk.gauntface.android.admob.models.RawSite; 
import co.uk.gauntface.android.admob.models.SiteStat; 
import co.uk.gauntface.android.admob.networking.AdmobDownloadListener; 
import co.uk.gauntface.android.admob.networking.SiteStatService; 
import co.uk.gauntface.android.admob.views.AccountSummaryAdapter; 
import co.uk.gauntface.android.admob.views.SlidingLayout; 
import co.uk.gauntface.android.admob.views.TabBarScrollView; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.View; 
import android.widget.TextView; 

public class AccountSummary extends AdmobActivity 
{ 
private final static String TAG = "admob"; 

public static final String ACCOUNT_SUMMARY_INTENT_EXTRA_ID = "AccountSummaryIntentExtraID"; 

private String mAccountID; 
private RawSite mRawSiteData; 

private Handler mHandler; 
private SiteStatService mSiteStatService; 
private ArrayList<SiteStat> mSiteStatData; 

private ActionBarHelper mActionBarHelper; 

private TextView mAppTitleTextView; 
private TabBarScrollView mTabBarScrollView; 
private SlidingLayout mSlidingLayout; 
private AccountSummaryAdapter mAdapter; 

/** Called when the activity is first created. */ 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.account_summary); 

    mAccountID = getIntent().getExtras().getString(ACCOUNT_SUMMARY_INTENT_EXTRA_ID); 
    mSiteStatService = new SiteStatService(getApplicationContext()); 
    //mChartAdapter = new PointPositionAdapter(getApplicationContext()); 

    initActivity(); 

    setUpUI(); 

    if(getLastNonConfigurationInstance() != null) { 
    mSiteStatData = (ArrayList<SiteStat>) getLastNonConfigurationInstance(); 
    mAdapter.setSiteStatData(mSiteStatData); 
    } else { 
    updateSiteStatData(); 
    } 
} 

/**public void onConfigurationChanged (Configuration newConfig) { 
    super.onConfigurationChanged(newConfig); 
    setContentView(R.layout.account_summary); 

    setUpUI(); 
}**/ 

@Override 
public Object onRetainNonConfigurationInstance() { 
    return mSiteStatData; 
} 

private void initActivity() { 
    mHandler = new Handler() { 
    public void handleMessage(Message msg) { 
    switch(msg.arg1) { 
    default: 
    break; 
    } 
    } 
    }; 

    mAdapter = new AccountSummaryAdapter(getApplicationContext(), new Integer[]{ 
    R.string.revenue, 
    R.string.ecpm, 
    R.string.requests, 
    R.string.impressions, 
    R.string.fill_rate, 
    R.string.ctr 
    }); 

    DatabaseManager dbManager = new DatabaseManager(getApplicationContext()); 
    dbManager.open(); 
    mRawSiteData = dbManager.getSite(mAccountID); 
    dbManager.close(); 

} 

private void setUpUI() { 
    mActionBarHelper = new ActionBarHelper(this); 

    mAppTitleTextView = (TextView) findViewById(R.id.AccountSummaryAppTitleTextView); 
    mAppTitleTextView.setText(mRawSiteData.getSiteName()); 

    mTabBarScrollView = (TabBarScrollView) findViewById(R.id.AccountSummaryTabBarScrollView); 
    mTabBarScrollView.setAdapter(mAdapter.getTabBarAdapter()); 
    mTabBarScrollView.setOnItemOnClickListener(mAdapter); 

    mSlidingLayout = (SlidingLayout) findViewById(R.id.AccountSummarySlidingLayout); 
    mSlidingLayout.setAdapter(mAdapter.getSlidingLayoutAdapter()); 
    mSlidingLayout.setOnDisplayChangeListener(mAdapter); 
} 

private void updateSiteStatData() { 
    mActionBarHelper.incrementRequests(); 
    int daysToGet = getResources().getInteger(R.integer.account_summary_days); 
    mSiteStatService.downloadDailySiteStats(daysToGet, mRawSiteData.getSiteID(), new AdmobDownloadListener() { 

    public void onDownloadSuccess(Object obj) { 
    mActionBarHelper.decrementRequests(); 
    mSiteStatData = (ArrayList<SiteStat>) obj; 

    //mAdapter.setSiteStatData(mSiteStatData); 
    } 

    public void onDownloadError(int errorCode, String errorMsg) { 
    mActionBarHelper.decrementRequests(); 
    displayErrorMessage(errorCode, errorMsg); 
    } 
    }); 
} 

public void onClick(View v) { 
    switch(v.getId()) 
    { 
    case R.id.ActionBarRefreshImageButton: 
    updateSiteStatData(); 
    break; 
    } 
} 
} 

它將顯示視圖細,然而SlidingLayout實際上會出現包含在LinearLayout中空白(即,其不會膨脹的觀點

對於SlidingLayout的源代碼是:

package co.uk.gauntface.android.admob.views; 

import co.uk.gauntface.android.admob.R; 
import android.content.Context; 
import android.database.DataSetObserver; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewConfiguration; 
import android.widget.Adapter; 
import android.widget.HorizontalScrollView; 
import android.widget.LinearLayout; 

public class SlidingLayout extends HorizontalScrollView { 

private static final String TAG = "admob"; 

private int mSelectedPosition; 
private int mNewSelectedPosition; 
private LinearLayout mContainerLinearLayout; 

private int mScaledTouchSlop; 

private float mPrevX; 

private int mItemCount; 
private boolean mIsTouchEventScroll; 

private SlidingLayoutAdapter mAdapter; 
private DataSetObserver mDataSetObserver; 
private OnDisplayChangeListener mDisplayChangeListener; 

public SlidingLayout(Context context) { 
    super(context); 

    constructor(); 
} 

public SlidingLayout(Context context, AttributeSet attrs) { 
    super(context, attrs); 

    constructor(); 
} 

public SlidingLayout(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 

    constructor(); 
} 

private void constructor() { 
    Log.v(TAG, "SlidingLayout: constructor()"); 
    mSelectedPosition = 0; 
    mNewSelectedPosition = 0; 

    mItemCount = 0; 

    mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    Log.v(TAG, "SlidingLayout: onTouchEvent()"); 
    int action = event.getAction(); 

    switch (action) { 
    case MotionEvent.ACTION_DOWN: 
    break; 
    case MotionEvent.ACTION_MOVE: 
    int deltaX = (int) (mPrevX - event.getX()); 
    scrollBy(deltaX, 0); 
    break; 
    case MotionEvent.ACTION_UP: 
    animateToPosition(); 
    } 

    mPrevX = event.getX(); 

    return true; 
} 

private void animateToPosition() { 
    Log.v(TAG, "SlidingLayout: animateToPosition()"); 
    double scrollX = getScrollX(); 
    int screenWidth = getWidth(); 

    double ratio = scrollX/(double) screenWidth; 
    int whichScreen = (int) Math.round(ratio); 

    if(whichScreen >= 0 && whichScreen < mItemCount) { 
    int newX = whichScreen * screenWidth; 
    //int screenDiff = whichScreen - mDisplayedView; 
    int screenDiff = whichScreen - mSelectedPosition; 
    switch(screenDiff) { 
    case -1: 
    mNewSelectedPosition = mSelectedPosition - 1; 
    break; 
    case 0: 
    mNewSelectedPosition = mSelectedPosition; 
    break; 
    case 1: 
    mNewSelectedPosition = mSelectedPosition + 1; 
    break; 
    } 

    if(mNewSelectedPosition < 0) { 
    mNewSelectedPosition = 0; 
    } else if(mNewSelectedPosition >= mItemCount) { 
    mNewSelectedPosition = mItemCount - 1; 
    } 

    mIsTouchEventScroll = true; 
    smoothScrollTo(newX, 0); 
    } 
} 

public void setOnDisplayChangeListener(OnDisplayChangeListener changeListener) { 
    mDisplayChangeListener = changeListener; 
} 

public void setAdapter(SlidingLayoutAdapter adapter) { 
    Log.v(TAG, "SlidingLayout: setAdapter()"); 
    if(mContainerLinearLayout == null) { 
    mContainerLinearLayout = new LinearLayout(getContext()); 
    mContainerLinearLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
    mContainerLinearLayout.setOrientation(LinearLayout.HORIZONTAL); 
    mContainerLinearLayout.setBackgroundColor(getContext().getResources().getColor(R.color.admob_color)); 

    addView(mContainerLinearLayout); 
    } 

    if(mAdapter != null) { 
    mAdapter.unregisterDataSetObserver(mDataSetObserver); 
    } 

    mAdapter = adapter; 

    if(mAdapter != null) { 
    mDataSetObserver = new SlidingLayoutDataSetObserver(); 
    mAdapter.registerDataSetObserver(mDataSetObserver); 

    mItemCount = mAdapter.getCount(); 
    mSelectedPosition = mAdapter.getSelectedPosition(); 
    } else { 
    mItemCount = 0; 
    mSelectedPosition = 0; 

    return; 
    } 

    populateLayout(); 
} 

// l is horizontal scroll origin, t is vertical 
/**protected void onScrollChanged (int l, int t, int oldl, int oldt) { 
    super.onScrollChanged(l, t, oldl, oldt); 
    if(mIsTouchEventScroll) { 
    if(l % getWidth() == 0) { 
    mIsTouchEventScroll = false; 
    mSelectedPosition = mNewSelectedPosition; 
    if(mDisplayChangeListener != null) { 
    mDisplayChangeListener.onDisplayChange(l/getWidth()); 
    } 
    } 
    } 
}**/ 

private void populateLayout() { 
    Log.v(TAG, "SlidingLayout: populateLayout() - itemCount = "+mItemCount); 
    if(mContainerLinearLayout != null) { 
    mContainerLinearLayout.removeAllViews(); 
    } 

    for(int i = 0; i < mItemCount; i++) { 
    View v = mAdapter.getView(i, null, null); 
    v.setMinimumWidth(getWidth()); 
    mContainerLinearLayout.addView(v); 
    } 

    invalidate(); 

    scrollTo(mSelectedPosition * getWidth(), 0); 

    //View childView = mContainerLinearLayout.getChildAt(mSelectedPosition); 
    //mContainerLinearLayout.invalidate(); 
    //childView.invalidate(); 
    Log.v(TAG, "SlidingLayout: populateLayout() scrollX - "+getScrollX()); 
    //Log.v(TAG, "SlidingLayout: populateLayout() childView.width() - "+childView.getWidth()); 
    Log.v(TAG, "SlidingLayout: populateLayout() getWidth() - "+getWidth()); 
    Log.v(TAG, "SlidingLayout: populateLayout() getHeight() - "+getHeight()); 
    //Log.v(TAG, "SlidingLayout: populateLayout() container.getWidth() - "+mContainerLinearLayout.getWidth()); 
    //Log.v(TAG, "SlidingLayout: populateLayout() container.getHeight() - "+mContainerLinearLayout.getHeight()); 
} 

protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
    super.onSizeChanged(w, h, oldw, oldh); 
    if(mAdapter != null) { 
    mItemCount = mAdapter.getCount(); 
    mSelectedPosition = mAdapter.getSelectedPosition(); 
    } 
    populateLayout(); 
} 

public interface OnDisplayChangeListener { 
    abstract void onDisplayChange(int position); 
} 

public interface SlidingLayoutAdapter extends Adapter { 
    abstract int getSelectedPosition(); 
} 

public class SlidingLayoutDataSetObserver extends DataSetObserver { 
    public SlidingLayoutDataSetObserver() { 
    super(); 
    } 

    @Override 
    public void onChanged() { 
    Log.v(TAG, "SlidingLayout: onChanged()"); 
    mItemCount = mAdapter.getCount(); 
    mSelectedPosition = mAdapter.getSelectedPosition(); 
    populateLayout(); 
    } 

    @Override 
    public void onInvalidated() { 
    // Data is invalid so we should reset our state 
    //mItemCount = 0; 
    //mSelectedPosition = 0;//mAdapter.getSelectedPosition(); 
    //Log.v(TAG, "SlidingLayout: onInvalidated() removeAllViews"); 
    //mContainerLinearLayout.removeAllViews(); 
    //invalidate(); 
    //populateLayout(); 
    //requestLayout(); 
    Log.v(TAG, "SlidingLayout: onInvalidated()"); 

    mItemCount = mAdapter.getCount(); 
    mSelectedPosition = mAdapter.getSelectedPosition(); 
    populateLayout(); 
    } 
} 
} 

現在實際發生的事情是的LinearLayout(紅色)填充整個視圖,但任何C所有在LinearLayout上的getWidth()和getHeight()都返回0(在它自己的右邊足夠奇怪)。

但是,如果我觸摸單獨的Horizo​​ntalScrollView(主活動中的mTabBarScrollView),SlidingLayout實際上會調整/重繪/佈局自身。當Web服務使用調用notifyDataSetChanged()(導致resize/redraw/layout)的數據更新適配器時也會發生同樣的情況,但是在活動的onCreate方法中調用notifydatasetchanged()並不會產生相同的效果。

Android上的登錄顯示沒有錯誤是如此之多。

我不知道它可能是什麼/我能做些什麼來強制佈局更新/膨脹。

任何想法/建議將非常受歡迎。

乾杯, 馬特

附:恭喜,如果你做了這麼遠在帖子:)

回答

0

最終的解決方案是衡量孩子的意見,並通過在測量規範迫使他們是一個準確的寬度/高度:

v.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); 

原始代碼可以在github上找到https://github.com/gauntface/SideSwipeSnapViewLibrary

相關問題