放大列表视图中的中间元素

放大列表视图中的中间元素

本文介绍了放大列表视图中的中间元素 - android?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试放大最中心的列表视图项.(最终,我希望将其扩展为一种简单而轻盈的 3D 效果,元素在屏幕中间时会放大,在下方时会缩小,全黑背景和文本项会放大和缩小...)

Im trying to Enlarge the Centre most listview item. (Eventually, I hope to expand this into a sort of simple and light 3D effect that elements will appear to zoom in when in the middle of the screen and zoom out when they are down below, Total black background and text items zooming in and out... )

所以,我制作了一个虚拟的列表视图,每一行都是一个文本视图元素.下面,我有一个自定义适配器.

So, I've made a dummy listview, Each row is a textview element. Below, I have a custom Adapter.

我所做的唯一相关修改是:

The only relevant modification I've done is:

OnCreate() 中,我将以下变量传递给适配器:

In the OnCreate(), I pass the following variable to the adapter:

int v = (listview.getLastVisiblePosition() - listview.getFirstVisiblePosition()) + 1;

在适配器的 getView() 中,我得到了这个:

And in the Adapter's getView(), I've got this :

if (position == x/2) {
        textView.setHeight(100);
    }

无论如何,这里是所有代码,我跳过了导入:(它不是那么大!...大部分都很通用)

Anyways here's all of the code, I've skipped the imports: (It's not that big !... most of it is quite general)

MainActivity.java :

MainActivity.java :

    public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ListView listview = (ListView) findViewById(R.id.listview);
        String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
                "Blackberry", "WebOS", "Ubuntu", "Windows7","iPhone", "WindowsMobile",
                "Blackberry", "WebOS", "Ubuntu", "Windows7","iPhone", "WindowsMobile",
                "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X" };

        final ArrayList<String> list = new ArrayList<String>();
        for (int i = 0; i < values.length; ++i) {
            list.add(values[i]);
        }
        int v = (listview.getLastVisiblePosition() - listview.getFirstVisiblePosition()) + 1;


        final MySimpleArrayAdapter adapter = new MySimpleArrayAdapter(this, v, R.layout.row, list);
        listview.setAdapter(adapter);

        listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, final View view,
                    int position, long id) {

            }

        });
    }
}

MySimpleArrayAdapter.java

MySimpleArrayAdapter.java

 public class MySimpleArrayAdapter extends ArrayAdapter<String> {
    private final Context context;
    private final int x;

    HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();

    public MySimpleArrayAdapter(Context context, int a, int textViewResourceId,
            List<String> objects) {
        super(context, textViewResourceId, objects);
        this.context = context;
        this.x = a;
        for (int i = 0; i < objects.size(); ++i) {
            mIdMap.put(objects.get(i), i);
        }

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = inflater.inflate(R.layout.row, parent, false);
        TextView textView = (TextView) rowView.findViewById(R.id.textView1);

        if (position == x/2) {
            textView.setHeight(100);
        }

        return rowView;
    }

    @Override
    public long getItemId(int position) {
        String item = getItem(position);
        return mIdMap.get(item);
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }
}

此外,在我的 activity_main.xml 中我只有一个列表视图,而在row.xml"中我有一个文本视图..

Further, in my activity_main.xml I just have a single listview, and in "row.xml" I have a single textview..

问题:为什么没有出现文本?我清楚地将列表值添加到 textview 中.

Problems: Why is no text appearing? I clearly added the list values to the textview .

为什么最上面的元素大而不是中间的,我特地设置为中间的?

Why is the top most element big and not the middle one, I specifically set it to the middle one ?

这是我当前代码给出的屏幕:

Here's the screenie that my current code gives:

LOGCAT Error - KMDev 的解决方案

LOGCAT Error - KMDev's solution

10-06 17:54:02.529: E/AndroidRuntime(19596): FATAL EXCEPTION: main
10-06 17:54:02.529: E/AndroidRuntime(19596): java.lang.RuntimeException: Unable to start activity ComponentInfo{mple.finala/mple.finala.MainActivity}: java.lang.NullPointerException
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2077)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2104)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.app.ActivityThread.access$600(ActivityThread.java:134)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.os.Handler.dispatchMessage(Handler.java:99)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.os.Looper.loop(Looper.java:154)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.app.ActivityThread.main(ActivityThread.java:4624)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at java.lang.reflect.Method.invokeNative(Native Method)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at java.lang.reflect.Method.invoke(Method.java:511)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at dalvik.system.NativeStart.main(Native Method)
10-06 17:54:02.529: E/AndroidRuntime(19596): Caused by: java.lang.NullPointerException
10-06 17:54:02.529: E/AndroidRuntime(19596):    at mple.finala.MainActivity$2.onScroll(MainActivity.java:79)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.widget.AbsListView.invokeOnItemScrollListener(AbsListView.java:1297)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.widget.AbsListView.setOnScrollListener(AbsListView.java:1286)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at mple.finala.MainActivity.onCreate(MainActivity.java:58)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.app.Activity.performCreate(Activity.java:4479)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1050)
10-06 17:54:02.529: E/AndroidRuntime(19596):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2041)
10-06 17:54:02.529: E/AndroidRuntime(19596):    ... 11 more

编辑 2:

Complete Code,仍然给出null异常.

Complete Code, still giving null exception.

http://codeviewer.org/view/code:373d

推荐答案

需要解决一些问题.

  1. 您需要使用 ViewHolder 模式.关于 ListView,您真正需要了解的内容在 GoogleIO 2010 - ListView 世界 视频中.

在 getView 中调整项目的布局并不是一个好主意,因为这会对 ListView 使用的视图回收器产生负面影响.视频里也是这样.我真的鼓励您尝试找到一种不同的方式来显示您想要显示的内容.

It's not really a good idea to adjust the layout of an item in getView as that will negatively impact the view recycler that ListView uses. That is also in the video. I would really encourage you to try and find a different way to display what you want to display.

设置文本

  1. 您将项目所需的 x 维度传递给适配器的构造函数,而不是为其提供实际项目资源 ID.如果您传入正确的参数,ArrayAdapter 将为您设置文本.对于使用字符串资源和默认提供的列表项布局的简单示例:

  1. You're passing the x-dimension you want for an item in to your Adapter's constructor instead of supplying it an actual item resource id. ArrayAdapter will set your text for you if you pass in the right arguments. For a simple example using a string resource and the default provided list item layouts:

String[] mData = getResources().getStringArray(R.array.list_examples);
ArrayAdapter<String> mBaseAdapter =
            new ArrayAdapter<String>(context,
                                     android.R.layout.simple_list_item_1,
                                     android.R.id.text1,
                                     mListData);

  • 如果我是你,我只会让适配器设置文本并通过像这样调用 super 来获取项目布局:

  • If I were you, I'd just let the adapter set the text and grab that item layout by calling super like so:

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup){
        convertView = super.getView(position,convertView, viewGroup);
        //other code here
    }
    

  • 如果你真的想自己做,这里是ViewHolder模式

    If you really want to do it yourself, here it is with the ViewHolder pattern

        //This is the ViewHolder
        static class Holder{
            TextView mText;
        }
    
    
        @Override
        public View getView(int position, View convertView, ViewGroup viewGroup){
    
             convertView = super.getView(position, convertView, viewGroup);
    
             if (convertView == null){
                  // If you reach this, it most likely means you're not supplying the
                  // adapter the layout and textview resource it needs. You can
                  // just comment out your getView override and see if your text gets
                  // displayed.
             }
    
             Holder mHolder;
             if(convertView.getTag() == null){
                mHolder = new Holder();
                mHolder.mText = (TextView)convertView.findViewById(android.R.id.text1);
                convertView.setTag(mHolder);
             } else {
                mHolder = (Holder) convertView.getTag();
             }
    
             mHolder.mText.setText(getItem(position).toString());
        }
    

    关于 getXVisibleItem 方法

    // These are both implemented in AdapterView which means
    // they're flat list positions
    int firstVis = mList.getFirstVisiblePosition();
    int lastVis = mList.getLastVisiblePosition();
    
    /* This is the "conversion" from flat list positions to ViewGroup child positions */
    int count = lastVis - firstVis;
    
     /*  getChildAt(pos) is implemented in ViewGroup and has a different meaning for
     *  its position values. ViewGroup tracks visible items as children and is 0 indexed.
     *  This means you'll have 0 - X positions where X is however many items it takes
     *  to fill the visible area of your screen; usually less than 10. */
     View listItem = mList.getChildAt(count - ((int)count/2)); // This will get the middle
                                                            // item for you to adjust as
                                                            // you want.
    

    要在屏幕中间找到项目,您只需按照上面的评论,获取可见项目数并减去该数的一半.

    To find the item in the middle of the screen, you just need to take your visible item count and subtract half of that count as commented above.

    您需要在 ListView 上设置 AbsListView.OnScrollListener 并且当滚动停止,将您的调整应用于中间项目.例如:

    You will want to set an AbsListView.OnScrollListener on your ListView and when the scroll stops, apply your adjustments to the middle item. Ex:

    mList.setOnScrollListener(new OnScrollListener(){
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState){
    
        }
    
        @Override
        public void onScroll(AbsListView view,
                             int firstVisibleItem,
                             int visibleItemCount,
                             int totalItemCount){
    
            //Note that this is called when the scroll completes.
            //It gives us the positions we want so just calculate
            //the middle item, grab it and adjust the height directly
            //or by increasing margins if the item layout_height is
            //wrap_content. I'm not positive the margins do what you
            // need, but setting the height directly should.
            LinearLayout listItem = mList // <-- Replace LinearLayout with your layout
                          .getChildAt(visibleItemCount - ((int)visibleItemCount/2));
    
            //Make sure you use the right LayoutParams for the listItem Layout
            //If your listItem is a RelativeLayout for instance, you would use:
            // listItem.setLayoutParams(
            //      new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
            //                                      theHeightYouWantHere));
            listItem.setLayoutParams(
                    new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
                                                  theHeightYouWantHere));
    
            }
    });
    

    我已经写了一些关于 ListView 和 ExpandableListView 的切线相关的博客文章关于如何使用 childAt 策略刷新可见项目的代码示例(示例代码只是更改项目的文本/背景颜色).请原谅个人博客链接和它的样式(它是新的,需要更多的工作:),但代码运行良好.

    I've made a few tangentially related blog posts about ListView and ExpandableListView which have full code examples on how to refresh visible items (the example code just changes the text/background color of the item) which uses the childAt strategy. Pardon the personal blog link and the styling of it (it's new and needs more work :), but the code works well.

    只要您为项目布局使用 TextView(android.R.simple_list_item_1 是 TextView),这正是您想要的.如果您决定使用 ViewGroup 布局,则需要将 item.setHeight 替换为 LayoutParams 方法.

    This does exactly what you want as long as you're using a TextView for the item layout (android.R.simple_list_item_1 is a TextView). If you decide to use a ViewGroup layout, you'll need to replace item.setHeight with the LayoutParams method.

    mList.setOnScrollListener(new OnScrollListener(){
        @Override
        public void onScrollStateChanged(final AbsListView view, final int scrollState){
    
        }
    
        @Override
        public void onScroll(final AbsListView view,
                             final int firstVisibleItem,
                             final int visibleItemCount,
                             final int totalItemCount){
            if (visibleItemCount != 0){
    
                 Log.i( TAG, "firstVisibleItem: "
                             + firstVisibleItem
                             + "
    visibleItemCount: "
                             + visibleItemCount);
    
                 final int midPosition = visibleItemCount - (visibleItemCount / 2);
                 final TextView listItem = (TextView) mList.getChildAt(midPosition);
                 listItem.setHeight(500); //Only works if you're using
                                          //android.R.simple_list_item_1 since it's
                                          //not a ViewGroup, but rather a TextView
    
                 int count = visibleItemCount;
                 while (count >= 0){ // Here we need to loop through and make sure
                                     // all recycled items are returned to their
                                     // original height.
                     final TextView item = (TextView) mList.getChildAt(count);
                     if (item != null && count != midPosition){
                         item.setHeight(100);
                     }
                     count--;
                  }
            }
        }
    });
    

    这篇关于放大列表视图中的中间元素 - android?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-12 07:47