是否可以在Android中禁用listview中的特定列表项而不使用OnClickListener?

时间:2016-06-20 03:30:15

标签: android listview

我有一项任务,要跳过并禁用listview中的特定列表。但在做了一些研究之后,所有人都建议采用与here中相同的解决方案:

if(listview.getChildAt(selectedPosition).isEnabled())
{
    listview.getChildAt(selectedPosition).setEnabled(false);
}

并且还有一些建议如下here中的方法。

我想问的是,甚至可以在不使用OnClickListener或任何Listener的情况下禁用和跳过listview中的特定列表项?因为我是一个Android电视开发人员,所有访问都使用远程控制,意味着KeyEvent。

所以例如,在listview的第二个列表中,我可以在A和B之间切换。每当我选择A时,listview的第一个列表需要禁用,每当我选择B时,listview的第三个列表需要禁用。所以这些是基本的想法。

MenuView.java

public class MenuView extends FrameLayout {
    public static final int PAGE_INDEX_MIN = 1;
    private int mPageIndexMax; //Determined after firmware series identified

    private final LogUtility mLog = new LogUtility();

    private View mBaseView;
    private TextView mPublicModeTitle;
    private ListView mItemListView;

    private MenuPageAdapter mPageAdapter = null;
    private Range<Integer> mPageRange;
    private PageGenerator mPageGenerator;
    private int mPageIndex = -1;
    private int mItemCounter = 0;
    private int mVolumeFixedState;
    private static final int POUF_MENU_PAGE = 1;
    private static final int POUF_ITEM_VOLUME_MAXIMUM = 0;
    private static final int POUF_ITEM_VOLUME_FIXED = 1;
    private static final int POUF_ITEM_INPUT_MODE_START = 3;
    private static final int POUF_ITEM_RESET = 7;
    private static final int POUF_ITEM_EXECUTE = 8;
    private static final int POUF_VOLUME_FIXED_FIXED = 0;
    private static final int POUF_VOLUME_FIXED_VARIABLE = 1;

    /**
     * States
     */
    private boolean mCursorLocked = false;
    private boolean mSelectLocked = false;
    private boolean mApplyLocked = false;

    /**
     * Listener to catch extra keys
     */
    private ExtraKeyListener mExtraKeyListener = new ExtraKeyListener() {
        @Override
        public boolean onKey(ExtraKey extraKey, String deviceName) {
            View focusedView = findFocus();
            if (focusedView == null) {
                return false;
            }

            MenuItemInterface menuItem = (MenuItemInterface)focusedView.getTag(R.id.menu_base);
            if (menuItem == null) {
                // focused item is not menu item.
                return false;
            }

            switch (extraKey) {
                case KEYCODE_VOLUME_UP:
                    if (mSelectLocked == false) {
                        menuItem.select(1);
                    }
                    break;
                case KEYCODE_VOLUME_DOWN:
                    if (mSelectLocked == false) {
                        menuItem.select(-1);
                    }
                    break;
            }
            return true;
        }
    };

    public MenuView() {
        super(InstanceManager.getService());
        init();
    }

    /**
     * set page to show
     * @param index page index
     * @return true on success.
     */
    public boolean setPage(int index) {
        TvKeyReceiver tvKeyReceiver = TvKeyReceiver.getInstance();
        tvKeyReceiver.register();
        tvKeyReceiver.addListener(mExtraKeyListener);
        final int nextPageIndex = index;
        final int delayMs = 100;

        if (!mPageRange.contains(nextPageIndex)) {
            return false;
        }

        if (mPageAdapter != null) {
            mPageAdapter.destroy();
        }

        //TODO: repeating post is not good.

        lockCursor(true);
        lockSelect(true);
        lockApply(true);

        this.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (mPageAdapter != null && mPageAdapter.isDestroyFinished() == false) {
                    MenuView.this.postDelayed(this, delayMs);
                    return;
                }

                mPageIndex = nextPageIndex;
                mPageAdapter = mPageGenerator.generate(mPageIndex);
                mItemListView.setAdapter(mPageAdapter);
                mItemCounter = POUF_ITEM_VOLUME_MAXIMUM;
                updatePageViewText();
                lockCursor(false);
                lockSelect(false);
                lockApply(false);
            }
        }, delayMs);

        return true;
    }

    public void lockCursor(boolean enable) {
        mCursorLocked = enable;
    }

    public void lockSelect(boolean enable) {
        mSelectLocked = enable;
    }

    public void lockApply(boolean enable) {
        mApplyLocked = enable;
    }

    /**
     * Get busy status
     * @return
     */
    public boolean isBusy() {
        if (mPageAdapter == null) {
            return true;
        }
        if (mPageAdapter.areAnyItemsBusy()) {
            return true;
        }
        return false;
    }


    @Override
    protected void onAttachedToWindow() {
        post(new Runnable() {
            @Override
            public void run() {
                //Avoid no cursor issue in touch mode.
                if (isInTouchMode()) {
                    int keyCode = KeyEvent.KEYCODE_TAB; // KeyEvent.KEYCODE_DPAD_RIGHT;
                    injectKey(keyCode); // force to exit touch mode.
                }
                setPage(mPageIndex);
            }
        });
        super.onAttachedToWindow();
    }

    @Override
    protected void onDetachedFromWindow() {
        if (mPageAdapter != null) {
            mPageAdapter.destroy();
            mItemListView.setAdapter(null);
            mPageAdapter = null;
        }

        //TODO: how handle mPageAdapter.isDestroyFinished()?
        super.onDetachedFromWindow();
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        mVolumeFixedState = mPageGenerator.getVolumeFixedState();
        if (handleFocusOperation(event) ||
            handleItemOperation(event) ||
            handleOtherOperation(event)) {
            return true;
        }
        return super.dispatchKeyEvent(event);
    }

    private void updatePageViewText() {
        final Typeface typeface = Typeface.createFromFile("LCFONT_LATIN");
        mPublicModeTitle.setText("Public Mode");
        mPublicModeTitle.setTypeface(typeface);
        mVolumeFixedState = mPageGenerator.getVolumeFixedState();
        if (mVolumeFixedState == POUF_VOLUME_FIXED_FIXED) {
            mItemListView.setSelectionFromTop(POUF_ITEM_VOLUME_FIXED, 0);
            mItemCounter = POUF_ITEM_VOLUME_FIXED;
        }
    }

    /**
     * initialize. called from constructor.
     */
    private void init() {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        mBaseView = inflater.inflate(R.layout.menu_base, this, false);
        addView(mBaseView);
        mPublicModeTitle = (TextView)findViewById(R.id.menu_title);
        mItemListView = (ListView)findViewById(R.id.menu_item_list);
        mItemListView.setItemsCanFocus(true);
        mPageGenerator = new PageGeneratePouf(mItemListView, this);
        mPageIndexMax = mPageGenerator.getNumberOfPages();
        mPageRange = new Range<Integer>(PAGE_INDEX_MIN, mPageIndexMax);
        mPageIndex = POUF_MENU_PAGE;
        mItemCounter = POUF_ITEM_VOLUME_MAXIMUM;

        // avoid showing dummy string in a moment.
        updatePageViewText();

    }

    /**
     * called from dispatchKeyEvent
     */
    private boolean handleFocusOperation(KeyEvent event) {
        boolean handled = true;
        View focusedView = findFocus();

        if (focusedView == null) {
            mLog.d("currently no focus");
            if (mPageAdapter != null) {
                View view = mPageAdapter.getView(0, null, mItemListView);
                if (view != null) {
                    view.requestFocus();
                }
            }
            return true;
        }

        switch (event.getKeyCode()) {
        case KeyEvent.KEYCODE_DPAD_DOWN:
        case KeyEvent.KEYCODE_CHANNEL_DOWN: // next item
            if (event.getAction() == KeyEvent.ACTION_DOWN && mCursorLocked == false) {
                mLog.d("next item");
                if ((mItemCounter == POUF_ITEM_VOLUME_FIXED) && (mVolumeFixedState == POUF_VOLUME_FIXED_VARIABLE)) {
                    setFocusDown();
                }
                setFocusDown();
            }
            break;
        case KeyEvent.KEYCODE_DPAD_UP:
        case KeyEvent.KEYCODE_CHANNEL_UP: // previous item
            if (event.getAction() == KeyEvent.ACTION_DOWN && mCursorLocked == false) {
                mLog.d("previous item");
                if ((mItemCounter == POUF_ITEM_VOLUME_FIXED) && (mVolumeFixedState == POUF_VOLUME_FIXED_FIXED)) {
                    break;
                } else {
                    if ((mItemCounter == POUF_ITEM_INPUT_MODE_START) && (mVolumeFixedState == POUF_VOLUME_FIXED_VARIABLE)){
                        setFocusUp();
                    }
                    setFocusUp();
                }
            }
            break;
        default:
            handled = false;
            break;
        }

        return handled;
    }

    /**
     * called from dispatchKeyEvent
     */
    private boolean handleItemOperation(KeyEvent event) {
        boolean handled = true;

        View focusedView = findFocus();
        if (focusedView == null) {
            return false;
        }

        MenuItemInterface menuItem = (MenuItemInterface)focusedView.getTag(R.id.menu_base);
        if (menuItem == null) {
            // focused item is not menu item.
            return false;
        }

        switch (event.getKeyCode()) {
        case KeyEvent.KEYCODE_DPAD_CENTER:
            if (event.getAction() == KeyEvent.ACTION_DOWN && mApplyLocked == false) {
                mLog.d("apply");
                if (mItemCounter == POUF_ITEM_RESET) {
                    menuItem.apply();
                    setPage(PAGE_INDEX_MIN);
                } else if (mItemCounter == POUF_ITEM_EXECUTE) {
                    menuItem.apply();
                    MenuWindow.getInstance().close();
                }
            }
            break;
        case KeyEvent.KEYCODE_VOLUME_UP:
            if (event.getAction() == KeyEvent.ACTION_DOWN && mSelectLocked == false) {
                mLog.d("value1 +1");
                menuItem.select(1);
            }
            break;
        case KeyEvent.KEYCODE_VOLUME_DOWN:
            if (event.getAction() == KeyEvent.ACTION_DOWN && mSelectLocked == false) {
                mLog.d("value1 -1");
                menuItem.select(-1);
            }
            break;
        case KeyEvent.KEYCODE_DPAD_RIGHT:
            if (event.getAction() == KeyEvent.ACTION_DOWN && mSelectLocked == false) {
                mLog.d("value2 +1");
                menuItem.select(1);
            }
            break;
        case KeyEvent.KEYCODE_DPAD_LEFT:
            if (event.getAction() == KeyEvent.ACTION_DOWN && mSelectLocked == false) {
                mLog.d("value2 -1");
                menuItem.select(-1);
            }
            break;
        default:
            handled = false;
            break;
        }
        return handled;
    }

    /**
     * called from dispatchKeyEvent
     */
    private boolean handleOtherOperation(KeyEvent event) {
        boolean handled = true;

        switch (event.getKeyCode()) {
/*      case KeyEvent.KEYCODE_Q: // quit
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                mLog.i("quit");
                InstanceManager.getMenu().close();
            }
            break;
*/      default:
            handled = false;
            break;
        }

        return handled;
    }

    /**
     * Inject key event using InputManager.
     * @param keyCode
     */
    private void injectKey(int keyCode) {
        int source = InputDevice.SOURCE_KEYBOARD;
        int keyboard = KeyCharacterMap.VIRTUAL_KEYBOARD;
        long now = SystemClock.uptimeMillis();
        KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0, keyboard, 0, 0, source);
        KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0, keyboard, 0, 0, source);
        InputManager inputManager = (InputManager)InstanceManager.getService().getSystemService(Context.INPUT_SERVICE);
        inputManager.injectInputEvent(down, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
        inputManager.injectInputEvent(up, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
    }

    private void setFocusDown() {
        View newfocusedView = findFocus();
        View newView = newfocusedView.focusSearch(FOCUS_DOWN);
        if (newView != null) {
            newView.requestFocus(FOCUS_DOWN);
            mItemCounter += 1;
        }
    }

    private void setFocusUp() {
        View newfocusedView = findFocus();
        View newView = newfocusedView.focusSearch(FOCUS_UP);
        if (newView != null) {
            newView.requestFocus(FOCUS_UP);
            mItemCounter -= 1;
        }
    }
}

MenuPageAdapter.java

class MenuPageAdapter extends BaseAdapter {

    private MenuItemInterface[] mMenuItems;

    public MenuPageAdapter(MenuItemInterface[] menuItems) {
        this(Arrays.asList(menuItems));
    }

    public MenuPageAdapter(Collection<MenuItemInterface> menuItems) {
        mMenuItems = new MenuItemInterface[menuItems.size()];
        menuItems.toArray(mMenuItems);
    }

    /**
     * Start to destroy items.
     * @return
     */
    public boolean destroy() {
        boolean result = true;
        for (MenuItemInterface i: mMenuItems) {
            result &= i.destroy();
        }
        return result;
    }

    /**
     * @return true if all items are already destroyed.
     */
    public boolean isDestroyFinished() {
        for (MenuItemInterface i: mMenuItems) {
            if (i.isDestroyFinished() == false) {
                return false;
            }
        }
        return true;
    }

    @Override
    public int getCount() {
        return mMenuItems.length;
    }

    @Override
    public Object getItem(int position) {
        return mMenuItems[position];
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return mMenuItems[position].getView();
    }

    @Override
    public int  getViewTypeCount() {
        return 1; // TODO: should return 0? (because getItemViewType always return IGNORE_ITEM_VIEW_TYPE)
    }

    @Override
    public int getItemViewType(int position) {
        return BaseAdapter.IGNORE_ITEM_VIEW_TYPE;
    }

    /**
     * Get busy status.
     * @return
     */
    public boolean areAnyItemsBusy() {
        for (MenuItemInterface mi: mMenuItems) {
            if (mi.isBusy()) {
                return true;
            }
        }
        return false;
    }
}

0 个答案:

没有答案