Android ListView选中项居中放大(使用上下键控制,非触屏)

最近有一个功能机项目(不支持触屏)需要实现ListView选中项停在中间放大的效果,网络上的大多是用手滑动屏幕的效果,只能自己写一个。
效果实现了,但是还有小问题。实现原理主要是
1调用setSelection方法 使item项向上一项或向下一项
2调用setSelectionFromTop使选中项居于屏幕中间
这样有几个问题:
1首位几项无法居中(可以使用填充空白项的方案解决)
2按上下键移动item时,会看到listview轻微抖动(原因是setSelection会将选中项挪到listview可见部分的最顶部,之后setSelectionFromTop又让item项向下移动,该问题暂时没有解决思路,有能解决的大侠请多多指教)
下面上demo
1.item布局

<?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="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

2.页面布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="${relativePackage}.${activityClass}" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</LinearLayout>

3.Adapter

/**
 * Created by caihuijian on 18-2-7.
 */

public class ReportSpinnerAdapter extends BaseAdapter {

    private static String TAG = "ReportSpinnerAdapter";
    private Context context;
    private List<String> str;

    private ListView list;
    public static int select_item = -1;

    //隐藏条目和偏移量的基数
    private int n = 1;

    public ReportSpinnerAdapter(Context context, List<String> str, ListView list) {
        this.context = context;
        this.str = str;
        this.list = list;
    }

    @Override
    public int getCount() {
        return str.size();
    }

    @Override
    public Object getItem(int position) {
        return str.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder hold;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.item,
                    parent, false);
            hold = new ViewHolder();
            hold.textView = (TextView) convertView.findViewById(R.id.text);
            convertView.setTag(hold);
        } else {
            hold = (ViewHolder) convertView.getTag();
        }
        hold.textView.setText(str.get(position));

        Log.v(TAG, "MainActivity.select_item " + MainActivity.select_item
                + " position " + position);
        // 选中项放大
        if (MainActivity.select_item == position) {
            hold.textView.setTextSize(17); // 选中的Item字体大小33
            hold.textView.setAlpha(0.9f);
        } else {
            // 非选中项缩小 透明化
            hold.textView.setTextSize(15); // 未选中的Item字体大小30
            hold.textView.setAlpha(0.5f);
        }

        if (n <= 1) {
            n = getVisibleCount() / 2;
        }
        if (position <= n || (position >= (str.size() - n - 1))) {
            // 需要隐藏首尾的(visibleCount+1/2)个条目
            Log.v(TAG, "position " + position + " str.size() " + str.size()
                    + " n " + n);
            hold.textView.setAlpha(0.0f);
        }
        return convertView;
    }

    static class ViewHolder {
        TextView textView;
    }

    public int getN() {
        return n;
    }

    public int getVisibleCount() {
        int tempCount = (list.getLastVisiblePosition())
                - list.getFirstVisiblePosition();
        return tempCount;
    }
}

4.主界面

public class MainActivity extends ListActivity {

    private static String TAG = "MainActivity";
    ReportSpinnerAdapter adapter;
    ListView listView;
    public static int select_item = 1;

    // TODO int n//n为不显示数目

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

        // 模拟数据初始化
        List<String> datas = new ArrayList<String>();
        for (int i = 0; i < 20; i++) {
            datas.add("test " + i);
        }
        adapter = new ReportSpinnerAdapter(this, datas, getListView());
        listView = getListView();
        listView.setAdapter(adapter);
        listView.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> arg0, View arg1,
                    int arg2, long arg3) {
                Log.v(TAG, "onItemSelected");
                // 存储选中项位置 在adapter使用
                select_item = arg2;
                // 选中后将选中项挪到屏幕中间
                getListView().smoothScrollToPositionFromTop(select_item,
                        (int) getCenterY(), 1);
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });
    }

    @Override
    protected void onResume() {
        // 初始化默认选择第2项,位置在屏幕中间
        getListView().setSelectionFromTop(3, (int) getCenterY());
        super.onResume();
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        final int keyCode = event.getKeyCode();
        final int action = event.getAction();
        int adapterCount = adapter.getCount();

        // 屏蔽连续按下事件,只监听up事件
        if (action != KeyEvent.ACTION_UP && keyCode != KeyEvent.KEYCODE_BACK) {
            return false;
        } else {
            switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_DOWN:
                Log.v(TAG, "down break select_item" + select_item
                        + " adapterCount " + adapterCount);
                // 移动到倒数第n项 屏蔽KEYCODE_DPAD_DOWN事件
                if (select_item == adapterCount - adapter.getN() - 2) {
                    return false;
                }
                // 移到下一项
                getListView().setSelection(select_item + 1);
                break;
            case KeyEvent.KEYCODE_DPAD_UP:
                Log.v(TAG, "up break select_item" + select_item);
                // 移动到第n项 屏蔽KEYCODE_DPAD_UP事件
                if (select_item == adapter.getN() + 1) {
                    return false;
                }
                // 移到上一项
                getListView().setSelection(select_item - 1);
                break;
            case KeyEvent.KEYCODE_DPAD_CENTER:
                return true;
            default:
                return super.dispatchKeyEvent(event);
            }
        }

        return super.dispatchKeyEvent(event);
    }

    private double getCenterY() {
        // 计算行高
        View listItem = adapter.getView(0, null, listView);
        listItem.measure(0, 0);
        int height = listItem.getMeasuredHeight() + listView.getDividerHeight();

        // 计算显示条目
        // 计算偏移量
        return (adapter.getN() * height);
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值