缩放ListView项目Android

时间:2014-08-12 16:41:16

标签: android android-layout android-listview

我想缩放所有ListView项目,但只有一些项目正在缩放。

这是我的see_share_list_page_list_item_1.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="116dp"
    android:orientation="horizontal">

    <RelativeLayout
        android:layout_width="148dp"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/ivOfferImage"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:scaleType="fitXY"
            android:src="@drawable/ic_launcher"/>

        <!--<ImageView
            android:id="@+id/ivOfferIcon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:src="@drawable/ic_launcher"/>-->

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tvOfferTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:text="Offer title"
            android:textColor="#312F30"
            android:textSize="17sp"/>

        <TextView
            android:id="@+id/tvOfferDescription"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tvOfferTitle"
            android:layout_marginTop="5dp"
            android:text="Offer description"
            android:textColor="#312F30"
            android:maxLines="3"
            android:textSize="12sp"/>

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_below="@+id/tvOfferDescription">

            <ImageView
                android:id="@+id/ivOfferPrice"
                android:layout_width="20dp"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_gravity="center_vertical"
                android:adjustViewBounds="true"
                android:contentDescription="image"
                android:src="@drawable/ic_launcher"/>

            <TextView
                android:id="@+id/tvOfferPrice"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignBottom="@id/ivOfferPrice"
                android:layout_marginLeft="5dp"
                android:layout_toRightOf="@+id/ivOfferPrice"
                android:gravity="bottom"
                android:text="115"
                android:textColor="#38BA60"
                android:textSize="26sp"
                android:textStyle="bold"/>

            <TextView
                android:id="@+id/tvOfferPriceHeader"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignBottom="@+id/ivOfferPrice"
                android:layout_marginLeft="3dp"
                android:layout_toRightOf="@+id/tvOfferPrice"
                android:gravity="bottom"
                android:text="cur"
                android:textColor="#38BA60"
                android:textSize="20sp"
                android:textStyle="bold"/>

            <LinearLayout
                android:id="@+id/rlOfferDistance"
                android:layout_width="81dp"
                android:layout_height="24dp"
                android:layout_alignBottom="@id/ivOfferPrice"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@+id/tvOfferPriceHeader"
                android:gravity="center"
                android:background="#F00">

                <ImageView
                    android:id="@+id/ivOfferMarker"
                    android:layout_width="11dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="6dp"
                    android:adjustViewBounds="true"
                    android:src="@drawable/ic_launcher"/>

                <TextView
                    android:id="@+id/tvOfferDistance"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="13dp"
                    android:gravity="center"
                    android:text="600"
                    android:textColor="#FFFFFF"
                    android:textSize="15sp"/>

                <TextView
                    android:id="@+id/tvOfferDistanceHeader"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:layout_marginLeft="3dp"
                    android:text="m"
                    android:textColor="#FFFFFF"
                    android:textSize="15sp"/>
            </LinearLayout>

            <TextView
                android:id="@+id/tvCreateRouteToTheOffer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBottom="@id/rlOfferDistance"
                android:layout_alignParentRight="true"
                android:layout_gravity="center"
                android:text="create the route"
                android:textColor="#FF3A4A"
                android:textSize="12sp"/>
        </RelativeLayout>
    </RelativeLayout>
</LinearLayout>

这是我的see_share_list_page_1.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="533dp"
          android:layout_height="947dp">
    <ListView
        android:id="@+id/lvOffersOne"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:dividerHeight="24dp"
        android:divider="@android:color/transparent"/>

</LinearLayout>

这是我的Test.java

package com.googlion.shield.demonstration;


import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
//TODO ignore this
//import com.example.starfishapp.R;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Test extends Activity{

    private ListView offersLV;
    private List<Map<String, String>> offersList;
    private PageScaler pageScaler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.see_share_list_page_1);
        initializeFields();
        addOffersToList();
        setListAdapterForOffersLV();

        pageScaler.scaleThePage();
    }

    private void initializeFields() {
        offersLV = (ListView) findViewById(R.id.lvOffersOne);
        offersList = new LinkedList<Map<String, String>>();
        pageScaler = new PageScaler(Test.this);
    }


    private void addOffersToList() {
        final int LENGTH = 10;
        for (int i = 0; i < LENGTH; ++i) {
            addOfferToList();
        }
    }

    private void addOfferToList() {
        final Map<String, String> M = new HashMap<String, String>();
        M.put("Offer title", "Offer title");
        M.put("Offer description", "Offer description");
        M.put("Offer price", "115");
        M.put("Offer distance", "600");
        offersList.add(M);
    }

    private void setListAdapterForOffersLV() {
        final ListAdapter LA = getListAdapterForOffersLV();
        offersLV.setAdapter(LA);
    }

    private ListAdapter getListAdapterForOffersLV() {
        final Context C = Test.this;
        final int RESOURCE = R.layout.see_share_list_page_list_item_1;
        final String[] FROM = getOfferHeadersArray();
        final int[] TO = getOfferHeadersIdsArray();
        return new SimpleAdapter(C, offersList, RESOURCE, FROM, TO);
    }

    private String[] getOfferHeadersArray() {
        final String[] S = new String[4];
        S[0] = "Offer title";
        S[1] = "Offer description";
        S[2] = "Offer price";
        S[3] = "Offer distance";
        return S;
    }

    private int[] getOfferHeadersIdsArray() {
        final int[] I = new int[4];
        I[0] = R.id.tvOfferTitle;
        I[1] = R.id.tvOfferDescription;
        I[2] = R.id.tvOfferPrice;
        I[3] = R.id.tvOfferDistance;
        return I;
    }        

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

        pageScaler.scale(offersLV);
    }
}

这是我的PageScaler.java

package com.googlion.shield.demonstration;

import static android.R.attr.state_checked;
import static android.R.id.*;
import static android.graphics.Bitmap.*;
import static android.util.DisplayMetrics.*;
import static android.util.StateSet.*;
import static android.util.TypedValue.*;
import static android.view.ViewGroup.LayoutParams.*;
import static java.lang.Math.*;

import android.app.*;
import android.content.res.*;
import android.graphics.*;
import android.graphics.drawable.*;
import android.os.*;
import android.util.*;
import android.view.*;
import android.view.ViewGroup.*;
import android.widget.*;
// TODO ignore this
//import com.example.starfishapp.R;

public class PageScaler {

    private Activity requester;
    private View currentView;
    private LayoutParams currentViewLayoutParameters;
    private float scale;
    private int originalDrawableResourceId;
    private Bundle originalDrawablesResourceIds;

    public PageScaler(final Activity REQUESTER) {
        requester = REQUESTER;
        currentView = getRootViewFromRequester();
        currentViewLayoutParameters = currentView.getLayoutParams();
        scale = getScaleFromRootViewAndRequester();
        originalDrawableResourceId = 0;
        originalDrawablesResourceIds = new Bundle();
    }

    private View getRootViewFromRequester() {
        final View V = requester.findViewById(content);
        final ViewGroup VG = (ViewGroup) V;
        final int ROOT_VIEW_INDEX = 0;
        return VG.getChildAt(ROOT_VIEW_INDEX);
    }

    private float getScaleFromRootViewAndRequester() {
        final DisplayMetrics DM = getDisplayMetricsFromRequester();
        final float SCREEN_WIDTH = (float) DM.widthPixels;
        final float SCREEN_HEIGHT = (float) DM.heightPixels;
        final int BASE_DENSITY = DENSITY_LOW;
        final float CURRENT_DENSITY = (float) DM.densityDpi;
        final float DENSITY_SCALE = CURRENT_DENSITY / BASE_DENSITY;
        final float ROOT_WIDTH = currentViewLayoutParameters.width;
        final float SCALED_ROOT_WIDTH = ROOT_WIDTH / DENSITY_SCALE;
        final float ROOT_HEIGHT = currentViewLayoutParameters.height;
        final float SCALED_ROOT_HEIGHT = ROOT_HEIGHT / DENSITY_SCALE;
        final float HORIZONTAL_SCALE = SCREEN_WIDTH / SCALED_ROOT_WIDTH;
        final float VERTICAL_SCALE = SCREEN_HEIGHT / SCALED_ROOT_HEIGHT;
        return min(HORIZONTAL_SCALE, VERTICAL_SCALE) / DENSITY_SCALE;
    }

    private DisplayMetrics getDisplayMetricsFromRequester() {
        final DisplayMetrics DM = new DisplayMetrics();
        final WindowManager WM = requester.getWindowManager();
        final Display D = WM.getDefaultDisplay();
        D.getMetrics(DM);
        return DM;
    }

    public void scaleThePage() {
        if (pageIsDefinedToBeScalable()) {
            scale();
        }
    }

    private boolean pageIsDefinedToBeScalable() {
        boolean b = currentViewWidthIsNotDefinedBySpecialValue();
        b &= currentViewHeightIsNotDefinedBySpecialValue();
        return b;
    }

    private boolean currentViewWidthIsNotDefinedBySpecialValue() {
        boolean b = currentViewLayoutParameters.width != MATCH_PARENT;
        b &= currentViewLayoutParameters.width != WRAP_CONTENT;
        return b;
    }

    private boolean currentViewHeightIsNotDefinedBySpecialValue() {
        boolean b = currentViewLayoutParameters.height != MATCH_PARENT;
        b &= currentViewLayoutParameters.height != WRAP_CONTENT;
        return b;
    }

    private void scale() {
        stretchPageToTheDeviceScreenSize();
        scale(currentView);
    }

    private void stretchPageToTheDeviceScreenSize() {
        currentViewLayoutParameters.width = MATCH_PARENT;
        currentViewLayoutParameters.height = MATCH_PARENT;
    }

    public void scale(final View V) {
        retrieveCurrentViewFrom(V);
        retrieveLayoutInformationFromCurrentView();
        scaleCurrentViewPadding();

        // TODO ignore this
        //if (currentViewIsScalable()) {
            scaleCurrentViewItself();
        //}
        if (currentViewHasScalableMargins()) {
            scaleCurrentViewMargins();
        }
        if (currentViewExtendsView()) {
            scaleCurrentViewMainParameter();
        }
        if (currentViewHasChildren()) {
            scaleChildren();
        }
    }

    private void retrieveCurrentViewFrom(final View V) {
        currentView = V;
    }

    private void retrieveLayoutInformationFromCurrentView() {
        currentViewLayoutParameters = currentView.getLayoutParams();
    }

    private void scaleCurrentViewPadding() {
        final int LEFT = (int) (currentView.getPaddingLeft() * scale);
        final int TOP = (int) (currentView.getPaddingTop() * scale);
        final int RIGHT = (int) (currentView.getPaddingRight() * scale);
        final int BOTTOM = (int) (currentView.getPaddingBottom() * scale);
        currentView.setPadding(LEFT, TOP, RIGHT, BOTTOM);
    }
// TODO ignore this
    /*private boolean currentViewIsScalable() {
        return !(currentView instanceof LineSeparator);
    }*/

    private void scaleCurrentViewItself() {
        if (currentViewWidthIsNotDefinedBySpecialValue()) {
            currentViewLayoutParameters.width *= scale;
        }
        if (currentViewHeightIsNotDefinedBySpecialValue()) {
            currentViewLayoutParameters.height *= scale;
        }
    }

    private boolean currentViewHasScalableMargins() {
        boolean b = /* // TODO ignore this 
        currentView instanceof SeekBarTextView;
        b |= currentView instanceof SegmentOfSeekBarScale;
        b = !b;
        b &=*/ currentViewLayoutParameters instanceof MarginLayoutParams;
        return b;
    }

    private void scaleCurrentViewMargins() {
        final MarginLayoutParams MLP = (MarginLayoutParams) currentViewLayoutParameters;
        MLP.leftMargin *= scale;
        MLP.rightMargin *= scale;
        MLP.topMargin *= scale;
        MLP.bottomMargin *= scale;
    }

    private boolean currentViewExtendsView() {
        boolean b = currentViewIsATextView();
        b |= currentViewIsASeekBar();
        b |= currentViewIsACompoundButton();
        return b;
    }

    private boolean currentViewIsATextView() {
        return currentView instanceof TextView;
    }

    private boolean currentViewIsASeekBar() {
        return currentView instanceof SeekBar;
    }

    private boolean currentViewIsACompoundButton() {
        return currentView instanceof CompoundButton;
    }

    private void scaleCurrentViewMainParameter() {
        if (currentViewIsATextView()) {
            scaleTextSize();
        }
        if (currentViewIsASeekBar()) {
            scaleSeekBarThumb();
        }
        if (currentViewIsACompoundButton()) {
            scaleCompoundButton();
        }
    }

    private void scaleTextSize() {
        final TextView TV = (TextView) currentView;
        final float OLD_SIZE = TV.getTextSize();
        final float NEW_SIZE = OLD_SIZE * scale;
        final int DIMENSION_UNIT = COMPLEX_UNIT_PX;
        TV.setTextSize(DIMENSION_UNIT, NEW_SIZE);
    }

    private void scaleSeekBarThumb() {
        retrieveThumbResourceId();
        //TODO ignore this
        // scaleThumb();
    }

    private void retrieveThumbResourceId() {
        //TODO ignore this
        //originalDrawableResourceId = R.drawable.seek_bar_thumb;
    }

    private void scaleThumb() {
        final Drawable D = getScaledDrawableFromItsResourceId();
        final SeekBar SB = (SeekBar) currentView;
        SB.setThumb(D);
    }

    private Drawable getScaledDrawableFromItsResourceId() {
        final Resources R = requester.getResources();
        final Drawable D = R.getDrawable(originalDrawableResourceId);
        final BitmapDrawable BD = (BitmapDrawable) D;
        final Bitmap SOURCE = BD.getBitmap();
        final int W = (int) (SOURCE.getWidth() * scale);
        final int H = (int) (SOURCE.getHeight() * scale);
        final boolean FILTER = false;
        final Bitmap B = createScaledBitmap(SOURCE, W, H, FILTER);
        return new BitmapDrawable(R, B);
    }

    private void scaleCompoundButton() {
        prepareCompoundButtonButtonDrawableForScaling();
        scaleCompoundButtonButtonDrawable();
    }

    private void prepareCompoundButtonButtonDrawableForScaling() {
        final Bundle B;
        //TODO ignore this
        /*if (currentViewIsARadioButton()) {
            B = getOriginalDrawablesResourceIdsForRadioButtonScaling();
        } else {
            B = getOriginalDrawablesResourceIdsForCheckBoxScaling();
        }
        originalDrawablesResourceIds = B;*/
    }

    private boolean currentViewIsARadioButton() {
        return currentView instanceof RadioButton;
    }

    private Bundle getOriginalDrawablesResourceIdsForRadioButtonScaling() {
        final Bundle B = new Bundle();
        // TODO ignore this
        /*final String CHECKED_STATE_KEY = "Drawable resource id for checked state";
        final String UNCHECKED_STATE_KEY = "Drawable resource id for unchecked state";
        final int CHECKED_STATE_VALUE = R.drawable.radio_checked_image;
        final int UNCHECKED_STATE_VALUE = R.drawable.radio_unchecked_image;
        B.putInt(CHECKED_STATE_KEY, CHECKED_STATE_VALUE);
        B.putInt(UNCHECKED_STATE_KEY, UNCHECKED_STATE_VALUE);*/
        return B;
    }

    private Bundle getOriginalDrawablesResourceIdsForCheckBoxScaling() {
        final Bundle B = new Bundle();
        // TODO ignore this
        /*
        final String CHECKED_STATE_KEY = "Drawable resource id for checked state";
        final String UNCHECKED_STATE_KEY = "Drawable resource id for unchecked state";
        final int CHECKED_STATE_VALUE = R.drawable.list_item_checked_image;
        final int UNCHECKED_STATE_VALUE = R.drawable.list_item_unchecked_image;
        B.putInt(CHECKED_STATE_KEY, CHECKED_STATE_VALUE);
        B.putInt(UNCHECKED_STATE_KEY, UNCHECKED_STATE_VALUE);*/
        return B;
    }

    private void scaleCompoundButtonButtonDrawable() {
        final Drawable D = getScaledButtonDrawableFromOriginalDrawablesResourceIds();
        final CompoundButton CB = (CompoundButton) currentView;
        CB.setButtonDrawable(D);
    }

    private Drawable getScaledButtonDrawableFromOriginalDrawablesResourceIds() {
        final Drawable CHECKED_STATE_DRAWABLE = getDrawableForCheckedState();
        final Drawable UNCHECKED_STATE_DRAWABLE = getDrawableForUncheckedState();
        final StateListDrawable SLD = new StateListDrawable();
        final int[] CHECKED_STATE_SET = {state_checked};
        SLD.addState(CHECKED_STATE_SET, CHECKED_STATE_DRAWABLE);
        SLD.addState(WILD_CARD, UNCHECKED_STATE_DRAWABLE);
        return SLD;
    }

    private Drawable getDrawableForCheckedState() {
        retrieveOriginalDrawableResourceIdForCheckedState();
        return getScaledDrawableFromItsResourceId();
    }

    private void retrieveOriginalDrawableResourceIdForCheckedState() {
        final String KEY = "Drawable resource id for checked state";
        final Bundle B = originalDrawablesResourceIds;
        originalDrawableResourceId = B.getInt(KEY);
    }

    private Drawable getDrawableForUncheckedState() {
        retrieveOriginalDrawableResourceIdForUncheckedState();
        return getScaledDrawableFromItsResourceId();
    }

    private void retrieveOriginalDrawableResourceIdForUncheckedState() {
        final String KEY = "Drawable resource id for unchecked state";
        final Bundle B = originalDrawablesResourceIds;
        originalDrawableResourceId = B.getInt(KEY);
    }

    private boolean currentViewHasChildren() {
        return currentView instanceof ViewGroup;
    }

    private void scaleChildren() {
        final ViewGroup VG = (ViewGroup) currentView;
        final int SIZE = VG.getChildCount();
        for (int i = 0; i < SIZE; ++i) {
            scale(VG.getChildAt(i));
        }
    }

    public void scaleChildrenOf(final ViewGroup VG) {
        final int SIZE = VG.getChildCount();
        for (int i = 0; i < SIZE; ++i) {
            scale(VG.getChildAt(i));
        }
    }

    public void scale(final ListView LV) {
        //TODO 
        /* ignore this
            final int DIVIDER_OLD_HEIGHT = LV.getDividerHeight();
            final int DIVIDER_NEW_HEIGHT = (int) (DIVIDER_OLD_HEIGHT * scale);
            LV.setDividerHeight(DIVIDER_NEW_HEIGHT);
            Toast.makeText(requester, "Height: " + DIVIDER_OLD_HEIGHT, Toast.LENGTH_SHORT).show();*/

        final int SIZE = LV.getCount();
        for (int i = 0; i < SIZE; ++i) {
            scale(LV.getAdapter().getView(i,LV.getChildAt(i),LV));
        }
        //TODO
    }
}

我在两个模拟器上测试了这个代码,这是我在Genymotion中创建的。
第一个仿真器^具有以下参数:
- 400 x 800像素;
- ldpi(120dpi);

第二个^^有一个以下参数:
800 x 1280像素;
xxhdpi(480dpi)。

^所有ListView项目在该模拟器上正确显示。因为我为该模拟器手动调整了我的xml文件。

^^只有部分ListView项目在该模拟器上正确显示(缩放)。

我建议你创建我上面提到的模拟器。它有助于查看我正在寻找解决问题的深度。

我试图评论可能产生错误的所有代码行。但是,如果我的代码仍然产生错误,请告诉我代码行。我会纠正他们。

我一直在寻找解决方案两天。

listView.getChildAt();
listView.setSelection();
listView.getSelectedView();
listView.getFocusedChild();
<!-- and other methods similar to them -->

所有这些都没有帮助解决问题。其中一些产生异常(如NullPointerException)。他们中的一些人什么都不做 我试图覆盖SimpleAdapter的getView()方法并使用LayoutInflater.inflate()。但那也行不通。它导致了NullPointerException 也许我做错了什么?

任何帮助将不胜感激。

我需要一个工作方法“public void scale(final ListView LV)”,它将扩展所有ListView项目。

修改
感谢Jim,我发现要扩展所有ListView项目,您需要:
1)覆盖getView()方法;
2)在该方法中使用这些代码行(或类似代码):

if(convertView==null) {
    // inflate the layout
    LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
    convertView = inflater.inflate(layoutResourceId, parent, false);
    pageScaler.scale(convertView);
}

如果您尝试使用这些代码行(或类似代码)

if(convertView==null) {
    // This a new view we inflate the new layout
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(layoutResourceId, null);
    pageScaler.scale(convertView);
}

您将获得NullPointerException(当您尝试扩展convertView时)。至少在我的情况下发生了这种情况。

1 个答案:

答案 0 :(得分:0)

不幸的是,您的方法不正确。您不应构建ListView,然后缩放图像。您应该使用自定义ArrayAdapter并在将每个项目传递到ListView时对其进行缩放。

例如:

http://www.javacodegeeks.com/2013/06/android-listview-custom-adapter-with-imageview.html

或在这里:

http://www.javacodegeeks.com/2013/09/android-listview-with-adapter-example.html