我想創建一個類,可以添加到佈局文件,具有適配器集,然後從DataSetObserver更新。充氣視圖並將它們添加到HorizontalScrollView內的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(在它自己的右邊足夠奇怪)。
但是,如果我觸摸單獨的HorizontalScrollView(主活動中的mTabBarScrollView),SlidingLayout實際上會調整/重繪/佈局自身。當Web服務使用調用notifyDataSetChanged()(導致resize/redraw/layout)的數據更新適配器時也會發生同樣的情況,但是在活動的onCreate方法中調用notifydatasetchanged()並不會產生相同的效果。
Android上的登錄顯示沒有錯誤是如此之多。
我不知道它可能是什麼/我能做些什麼來強制佈局更新/膨脹。
任何想法/建議將非常受歡迎。
乾杯, 馬特
附:恭喜,如果你做了這麼遠在帖子:)