2011-01-12 11 views
0

Ich versuche, eine Klasse zu erstellen, die zu einer Layoutdatei hinzugefügt werden kann, einen Adapter festlegen und dann von einem DataSetObserver aktualisieren.Aufblasen von Ansichten und Hinzufügen zu einem LinearLayout innerhalb eines HorizontalScrollView - Odd Behavior

Auf dem Nexus One scheint dies in der Regel gut zu funktionieren, aber auf der G1 bekomme ich ein seltsames Verhalten.

die Layout-Datei für die Aktivität ist also:

<?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> 

Jetzt ist der Grund, warum ich hier FillViewPort zu wahr ist, weil von einem ähnlichen Problem festgelegt habe: LinearLayout not expanding inside a ScrollView obwohl dies mein Problem nicht behoben hat.

Der Quellcode für die Aktivität ist.

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; 
    } 
} 
} 

die die Ansichten fein angezeigt wird, aber die SlidingLayout wird leer tatsächlich erscheinen (dh es werden die Ansichten nicht aufblasen in der Linearlayout enthalten

der Quellcode für das SlidingLayout ist:

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(); 
    } 
} 
} 

nun eigentlich das, was passiert, ist das Linearlayout (Farbe rot) füllt die gesamte Ansicht, aber jeder c alls to getWidth() und getHeight() auf der LinearLayout geben 0 zurück (ungerade genug in seinem eigenen Recht).

Aber wenn ich eine separate HorizontalScrollView (die mTabBarScrollView in der Hauptaktivität) berühren, wird die SlidingLayout tatsächlich Größe ändern/neu zeichnen/Layout selbst aus. Das Gleiche tritt auch auf, wenn ein Webdienst den Adapter mit Daten aktualisiert, die notifyDataSetChanged() aufrufen (wodurch die Größenänderung/Neuzeichnung/Layout verursacht wird), jedoch das Aufrufen von notifydatasetchanged() in der onCreate-Methode der Aktivität nicht den gleichen Effekt hat.

Die Anmeldung auf Android zeigt keine Fehler, was auch immer.

Ich weiß nicht, was es sein könnte/was ich tun kann, um die Aktualisierung der Layouts zu erzwingen.

Alle Ideen/Vorschläge wären sehr willkommen.

Cheers, Matt

P. S. Glückwunsch, wenn Sie es so weit in der Post gemacht :)

Antwort

0

Die Lösung am Ende war das Kind Ansicht und gibt in einer Maßnahme spec messen zu zwingen, eine exakte Breite/Höhe zu sein:

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

Der ursprüngliche Code kann auf github https://github.com/gauntface/SideSwipeSnapViewLibrary

gefunden werden
Verwandte Themen