Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03e931d3 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "add-work-tab"

* changes:
  Tests for personal and work tab logic.
  Add personal and work tabs to share sheet and intent picker.
parents 5e170351 b4fc3974
Loading
Loading
Loading
Loading
+37 −5
Original line number Diff line number Diff line
@@ -26,7 +26,9 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.PagerAdapter;
import com.android.internal.widget.ViewPager;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * Skeletal {@link PagerAdapter} implementation of a work or personal profile page for
@@ -34,6 +36,7 @@ import java.util.Objects;
 */
public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {

    private static final String TAG = "AbstractMultiProfilePagerAdapter";
    static final int PROFILE_PERSONAL = 0;
    static final int PROFILE_WORK = 1;
    @IntDef({PROFILE_PERSONAL, PROFILE_WORK})
@@ -41,10 +44,17 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {

    private final Context mContext;
    private int mCurrentPage;
    private OnProfileSelectedListener mOnProfileSelectedListener;
    private Set<Integer> mLoadedPages;

    AbstractMultiProfilePagerAdapter(Context context, int currentPage) {
        mContext = Objects.requireNonNull(context);
        mCurrentPage = currentPage;
        mLoadedPages = new HashSet<>();
    }

    void setOnProfileSelectedListener(OnProfileSelectedListener listener) {
        mOnProfileSelectedListener = listener;
    }

    Context getContext() {
@@ -57,15 +67,22 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
     * page and rebuilds the list.
     */
    void setupViewPager(ViewPager viewPager) {
        viewPager.setCurrentItem(mCurrentPage);
        viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                mCurrentPage = position;
                if (!mLoadedPages.contains(position)) {
                    getActiveListAdapter().rebuildList();
                    mLoadedPages.add(position);
                }
                if (mOnProfileSelectedListener != null) {
                    mOnProfileSelectedListener.onProfileSelected(position);
                }
            }
        });
        viewPager.setAdapter(this);
        viewPager.setCurrentItem(mCurrentPage);
        mLoadedPages.add(mCurrentPage);
    }

    @Override
@@ -90,7 +107,8 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
        return mCurrentPage;
    }

    UserHandle getCurrentUserHandle() {
    @VisibleForTesting
    public UserHandle getCurrentUserHandle() {
        return getActiveListAdapter().mResolverListController.getUserHandle();
    }

@@ -135,7 +153,8 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
     * <p>This method is meant to be implemented with an implementation-specific return type
     * depending on the adapter type.
     */
    abstract Object getAdapterForIndex(int pageIndex);
    @VisibleForTesting
    public abstract Object getAdapterForIndex(int pageIndex);

    @VisibleForTesting
    public abstract ResolverListAdapter getActiveListAdapter();
@@ -152,7 +171,9 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {

    abstract Object getCurrentRootAdapter();

    abstract ViewGroup getCurrentAdapterView();
    abstract ViewGroup getActiveAdapterView();

    abstract @Nullable ViewGroup getInactiveAdapterView();

    protected class ProfileDescriptor {
        final ViewGroup rootView;
@@ -160,4 +181,15 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
            this.rootView = rootView;
        }
    }

    public interface OnProfileSelectedListener {
        /**
         * Callback for when the user changes the active tab from personal to work or vice versa.
         * <p>This callback is only called when the intent resolver or share sheet shows
         * the work and personal profiles.
         * @param profileIndex {@link #PROFILE_PERSONAL} if the personal profile was selected or
         * {@link #PROFILE_WORK} if the work profile was selected.
         */
        void onProfileSelected(int profileIndex);
    }
}
 No newline at end of file
+36 −29
Original line number Diff line number Diff line
@@ -508,7 +508,6 @@ public class ChooserActivity extends ResolverActivity implements
    protected void onCreate(Bundle savedInstanceState) {
        final long intentReceivedTime = System.currentTimeMillis();
        // This is the only place this value is being set. Effectively final.
        //TODO(arangelov) - should there be a mIsAppPredictorComponentAvailable flag for work tab?
        mIsAppPredictorComponentAvailable = isAppPredictionServiceAvailable();

        mIsSuccessfullySelected = false;
@@ -689,29 +688,6 @@ public class ChooserActivity extends ResolverActivity implements
                mResolverDrawerLayout.setOnScrollChangeListener(this::handleScroll);
            }

            final View chooserHeader = mResolverDrawerLayout.findViewById(R.id.chooser_header);
            final float defaultElevation = chooserHeader.getElevation();
            final float chooserHeaderScrollElevation =
                    getResources().getDimensionPixelSize(R.dimen.chooser_header_scroll_elevation);

            mChooserMultiProfilePagerAdapter.getCurrentAdapterView().addOnScrollListener(
                    new RecyclerView.OnScrollListener() {
                        public void onScrollStateChanged(RecyclerView view, int scrollState) {
                        }

                        public void onScrolled(RecyclerView view, int dx, int dy) {
                            if (view.getChildCount() > 0) {
                                View child = view.getLayoutManager().findViewByPosition(0);
                                if (child == null || child.getTop() < 0) {
                                    chooserHeader.setElevation(chooserHeaderScrollElevation);
                                    return;
                                }
                            }

                            chooserHeader.setElevation(defaultElevation);
                        }
            });

            mResolverDrawerLayout.setOnCollapsedChangedListener(
                    new ResolverDrawerLayout.OnCollapsedChangedListener() {

@@ -1330,8 +1306,8 @@ public class ChooserActivity extends ResolverActivity implements
    }

    @Override
    public void onPrepareAdapterView(ResolverListAdapter adapter) {
        mChooserMultiProfilePagerAdapter.getCurrentAdapterView().setVisibility(View.VISIBLE);
    public void addUseDifferentAppLabelIfNecessary(ResolverListAdapter adapter) {
        mChooserMultiProfilePagerAdapter.getActiveAdapterView().setVisibility(View.VISIBLE);
        if (mCallerChooserTargets != null && mCallerChooserTargets.length > 0) {
            mChooserMultiProfilePagerAdapter.getActiveListAdapter().addServiceResults(
                    /* origTarget */ null,
@@ -2202,7 +2178,7 @@ public class ChooserActivity extends ResolverActivity implements
        if (mChooserMultiProfilePagerAdapter == null) {
            return;
        }
        RecyclerView recyclerView = mChooserMultiProfilePagerAdapter.getCurrentAdapterView();
        RecyclerView recyclerView = mChooserMultiProfilePagerAdapter.getActiveAdapterView();
        ChooserGridAdapter gridAdapter = mChooserMultiProfilePagerAdapter.getCurrentRootAdapter();
        if (gridAdapter == null || recyclerView == null) {
            return;
@@ -2328,6 +2304,8 @@ public class ChooserActivity extends ResolverActivity implements

    @Override
    public void onListRebuilt(ResolverListAdapter listAdapter) {
        setupScrollListener();

        ChooserListAdapter chooserListAdapter = (ChooserListAdapter) listAdapter;
        if (chooserListAdapter.mDisplayList == null
                || chooserListAdapter.mDisplayList.isEmpty()) {
@@ -2368,6 +2346,34 @@ public class ChooserActivity extends ResolverActivity implements
        }
    }

    private void setupScrollListener() {
        if (mResolverDrawerLayout == null) {
            return;
        }
        final View chooserHeader = mResolverDrawerLayout.findViewById(R.id.chooser_header);
        final float defaultElevation = chooserHeader.getElevation();
        final float chooserHeaderScrollElevation =
                getResources().getDimensionPixelSize(R.dimen.chooser_header_scroll_elevation);

        mChooserMultiProfilePagerAdapter.getActiveAdapterView().addOnScrollListener(
                new RecyclerView.OnScrollListener() {
                    public void onScrollStateChanged(RecyclerView view, int scrollState) {
                    }

                    public void onScrolled(RecyclerView view, int dx, int dy) {
                        if (view.getChildCount() > 0) {
                            View child = view.getLayoutManager().findViewByPosition(0);
                            if (child == null || child.getTop() < 0) {
                                chooserHeader.setElevation(chooserHeaderScrollElevation);
                                return;
                            }
                        }

                        chooserHeader.setElevation(defaultElevation);
                    }
                });
    }

    @Override // ChooserListCommunicator
    public boolean isSendAction(Intent targetIntent) {
        if (targetIntent == null) {
@@ -2475,7 +2481,8 @@ public class ChooserActivity extends ResolverActivity implements
     * row level by this adapter but not on the item level. Individual targets within the row are
     * handled by {@link ChooserListAdapter}
     */
    final class ChooserGridAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    @VisibleForTesting
    public final class ChooserGridAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private ChooserListAdapter mChooserListAdapter;
        private final LayoutInflater mLayoutInflater;

@@ -2905,7 +2912,7 @@ public class ChooserActivity extends ResolverActivity implements

            if (mDirectShareViewHolder != null && canExpandDirectShare) {
                mDirectShareViewHolder.handleScroll(
                        mChooserMultiProfilePagerAdapter.getCurrentAdapterView(), y, oldy,
                        mChooserMultiProfilePagerAdapter.getActiveAdapterView(), y, oldy,
                        getMaxTargetsPerRow());
            }
        }
+0 −5
Original line number Diff line number Diff line
@@ -245,11 +245,6 @@ public class ChooserListAdapter extends ResolverListAdapter {
        Collections.sort(mSortedList, new ChooserActivity.AzInfoComparator(mContext));
    }

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

    @Override
    public int getCount() {
        return getRankedTargetCount() + getAlphaTargetCount()
+13 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.app;

import android.annotation.Nullable;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
@@ -77,7 +78,8 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
    }

    @Override
    ChooserActivity.ChooserGridAdapter getAdapterForIndex(int pageIndex) {
    @VisibleForTesting
    public ChooserActivity.ChooserGridAdapter getAdapterForIndex(int pageIndex) {
        return mItems[pageIndex].chooserGridAdapter;
    }

@@ -121,10 +123,19 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
    }

    @Override
    RecyclerView getCurrentAdapterView() {
    RecyclerView getActiveAdapterView() {
        return getListViewForIndex(getCurrentPage());
    }

    @Override
    @Nullable
    RecyclerView getInactiveAdapterView() {
        if (getCount() == 1) {
            return null;
        }
        return getListViewForIndex(1 - getCurrentPage());
    }

    class ChooserProfileDescriptor extends ProfileDescriptor {
        private ChooserActivity.ChooserGridAdapter chooserGridAdapter;
        private RecyclerView recyclerView;
+118 −38
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -67,9 +68,12 @@ import android.view.WindowInsets;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Space;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;
import android.widget.Toast;

@@ -82,6 +86,7 @@ import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.widget.ResolverDrawerLayout;
import com.android.internal.widget.ViewPager;

import java.util.ArrayList;
import java.util.Arrays;
@@ -147,7 +152,10 @@ public class ResolverActivity extends Activity implements
    /**
     * TODO(arangelov): Remove a couple of weeks after work/personal tabs are finalized.
     */
    static final boolean ENABLE_TABBED_VIEW = false;
    @VisibleForTesting
    public static boolean ENABLE_TABBED_VIEW = false;
    private static final String TAB_TAG_PERSONAL = "personal";
    private static final String TAB_TAG_WORK = "work";

    private final PackageMonitor mPackageMonitor = createPackageMonitor();

@@ -418,12 +426,16 @@ public class ResolverActivity extends Activity implements
            Intent[] initialIntents,
            List<ResolveInfo> rList,
            boolean filterLastUsed) {
        // We only show the default app for the profile of the current user. The filterLastUsed
        // flag determines whether to show a default app and that app is not shown in the
        // resolver list. So filterLastUsed should be false for the other profile.
        ResolverListAdapter personalAdapter = createResolverListAdapter(
                /* context */ this,
                /* payloadIntents */ mIntents,
                initialIntents,
                rList,
                filterLastUsed,
                (filterLastUsed && UserHandle.myUserId()
                        == getPersonalProfileUserHandle().getIdentifier()),
                mUseLayoutForBrowsables,
                /* userHandle */ getPersonalProfileUserHandle());
        ResolverListAdapter workAdapter = createResolverListAdapter(
@@ -431,7 +443,8 @@ public class ResolverActivity extends Activity implements
                /* payloadIntents */ mIntents,
                initialIntents,
                rList,
                filterLastUsed,
                (filterLastUsed && UserHandle.myUserId()
                        == getWorkProfileUserHandle().getIdentifier()),
                mUseLayoutForBrowsables,
                /* userHandle */ getWorkProfileUserHandle());
        return new ResolverMultiProfilePagerAdapter(
@@ -495,12 +508,12 @@ public class ResolverActivity extends Activity implements
            mFooterSpacer = new Space(getApplicationContext());
        } else {
            ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
                .getCurrentAdapterView().removeFooterView(mFooterSpacer);
                .getActiveAdapterView().removeFooterView(mFooterSpacer);
        }
        mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
                                                                   mSystemWindowInsets.bottom));
        ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
            .getCurrentAdapterView().addFooterView(mFooterSpacer);
            .getActiveAdapterView().addFooterView(mFooterSpacer);
    }

    protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
@@ -817,7 +830,7 @@ public class ResolverActivity extends Activity implements

    public void onButtonClick(View v) {
        final int id = v.getId();
        ListView listView = (ListView) mMultiProfilePagerAdapter.getCurrentAdapterView();
        ListView listView = (ListView) mMultiProfilePagerAdapter.getActiveAdapterView();
        ResolverListAdapter currentListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter();
        int which = currentListAdapter.hasFilteredItem()
                ? currentListAdapter.getFilteredPosition()
@@ -898,7 +911,10 @@ public class ResolverActivity extends Activity implements

    @Override // ResolverListCommunicator
    public void onPostListReady(ResolverListAdapter listAdapter) {
        if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
                == UserHandle.myUserId()) {
            setHeader();
        }
        resetButtonBar();
        onListRebuilt(listAdapter);
    }
@@ -913,6 +929,9 @@ public class ResolverActivity extends Activity implements
                finish();
            }
        }

        final ItemClickListener listener = new ItemClickListener();
        setupAdapterListView((ListView) mMultiProfilePagerAdapter.getActiveAdapterView(), listener);
    }

    protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
@@ -1094,6 +1113,7 @@ public class ResolverActivity extends Activity implements
        return true;
    }

    @VisibleForTesting
    public void safelyStartActivity(TargetInfo cti) {
        // We're dispatching intents that might be coming from legacy apps, so
        // don't kill ourselves.
@@ -1222,9 +1242,6 @@ public class ResolverActivity extends Activity implements
                    + "cannot be null.");
        }
        boolean rebuildCompleted = mMultiProfilePagerAdapter.getActiveListAdapter().rebuildList();
        if (mMultiProfilePagerAdapter.getInactiveListAdapter() != null) {
            mMultiProfilePagerAdapter.getInactiveListAdapter().rebuildList();
        }
        if (useLayoutWithDefault()) {
            mLayoutId = R.layout.resolver_list_with_default;
        } else {
@@ -1272,45 +1289,99 @@ public class ResolverActivity extends Activity implements
            }
        }

        setupViewVisibilities(count);
        setupViewVisibilities();

        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
            setupProfileTabs();
        }

        return false;
    }

    private void setupViewVisibilities(int count) {
        if (count == 0
                && mMultiProfilePagerAdapter.getActiveListAdapter().getPlaceholderCount() == 0) {
            final TextView emptyView = findViewById(R.id.empty);
            emptyView.setVisibility(View.VISIBLE);
            findViewById(R.id.profile_pager).setVisibility(View.GONE);
    private void setupProfileTabs() {
        TabHost tabHost = findViewById(R.id.profile_tabhost);
        tabHost.setup();
        ViewPager viewPager = findViewById(R.id.profile_pager);
        TabHost.TabSpec tabSpec = tabHost.newTabSpec(TAB_TAG_PERSONAL)
                .setContent(R.id.profile_pager)
                .setIndicator(getString(R.string.resolver_personal_tab));
        tabHost.addTab(tabSpec);

        tabSpec = tabHost.newTabSpec(TAB_TAG_WORK)
                .setContent(R.id.profile_pager)
                .setIndicator(getString(R.string.resolver_work_tab));
        tabHost.addTab(tabSpec);

        TabWidget tabWidget = tabHost.getTabWidget();
        tabWidget.setVisibility(View.VISIBLE);
        resetTabsHeaderStyle(tabWidget);
        updateActiveTabStyle(tabHost);

        tabHost.setOnTabChangedListener(tabId -> {
            resetTabsHeaderStyle(tabWidget);
            updateActiveTabStyle(tabHost);
            if (TAB_TAG_PERSONAL.equals(tabId)) {
                viewPager.setCurrentItem(0);
            } else {
            onPrepareAdapterView(mMultiProfilePagerAdapter.getActiveListAdapter());
                viewPager.setCurrentItem(1);
            }
            setupViewVisibilities();
        });

        viewPager.setVisibility(View.VISIBLE);
        tabHost.setCurrentTab(mMultiProfilePagerAdapter.getCurrentPage());
        mMultiProfilePagerAdapter.setOnProfileSelectedListener(tabHost::setCurrentTab);
    }

    private void resetTabsHeaderStyle(TabWidget tabWidget) {
        for (int i = 0; i < tabWidget.getChildCount(); i++) {
            TextView title = tabWidget.getChildAt(i).findViewById(android.R.id.title);
            title.setTextColor(getColor(R.color.resolver_tabs_inactive_color));
            title.setAllCaps(false);
        }
    }

    private void updateActiveTabStyle(TabHost tabHost) {
        TextView title = tabHost.getTabWidget().getChildAt(tabHost.getCurrentTab())
                .findViewById(android.R.id.title);
        title.setTextColor(getColor(R.color.resolver_tabs_active_color));
    }

    private void setupViewVisibilities() {
        int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();
        boolean shouldShowEmptyState = count == 0
                && mMultiProfilePagerAdapter.getActiveListAdapter().getPlaceholderCount() == 0;
        //TODO(arangelov): Handle empty state
        if (!shouldShowEmptyState) {
            addUseDifferentAppLabelIfNecessary(mMultiProfilePagerAdapter.getActiveListAdapter());
        }
    }

    /**
     * Prepare the scrollable view which consumes data in the list adapter.
     * Add a label to signify that the user can pick a different app.
     * @param adapter The adapter used to provide data to item views.
     */
    public void onPrepareAdapterView(ResolverListAdapter adapter) {
        mMultiProfilePagerAdapter.getCurrentAdapterView().setVisibility(View.VISIBLE);
    public void addUseDifferentAppLabelIfNecessary(ResolverListAdapter adapter) {
        final boolean useHeader = adapter.hasFilteredItem();
        final ListView listView = (ListView) mMultiProfilePagerAdapter.getCurrentAdapterView();
        final ItemClickListener listener = new ItemClickListener();
        if (useHeader) {
            FrameLayout stub = findViewById(R.id.stub);
            stub.setVisibility(View.VISIBLE);
            TextView textView = (TextView) LayoutInflater.from(this).inflate(
                    R.layout.resolver_different_item_header, null, false);
            if (ENABLE_TABBED_VIEW) {
                textView.setGravity(Gravity.CENTER);
            }
            stub.addView(textView);
        }
    }

    private void setupAdapterListView(ListView listView, ItemClickListener listener) {
        listView.setOnItemClickListener(listener);
        listView.setOnItemLongClickListener(listener);

        if (mSupportsAlwaysUseOption || mUseLayoutForBrowsables) {
            listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
        }

        // In case this method is called again (due to activity recreation), avoid adding a new
        // header if one is already present.
        if (useHeader && listView.getHeaderViewsCount() == 0) {
            listView.setHeaderDividersEnabled(true);
            listView.addHeaderView(LayoutInflater.from(this).inflate(
                    R.layout.resolver_different_item_header, listView, false),
                    null, false);
        }
    }

    /**
@@ -1378,7 +1449,7 @@ public class ResolverActivity extends Activity implements
        }

        // When the items load in, if an item was already selected, enable the buttons
        ListView currentAdapterView = (ListView) mMultiProfilePagerAdapter.getCurrentAdapterView();
        ListView currentAdapterView = (ListView) mMultiProfilePagerAdapter.getActiveAdapterView();
        if (currentAdapterView != null
                && currentAdapterView.getCheckedItemPosition() != ListView.INVALID_POSITION) {
            setAlwaysButtonEnabled(true, currentAdapterView.getCheckedItemPosition(), true);
@@ -1388,8 +1459,18 @@ public class ResolverActivity extends Activity implements

    @Override // ResolverListCommunicator
    public boolean useLayoutWithDefault() {
        return mSupportsAlwaysUseOption
                && mMultiProfilePagerAdapter.getActiveListAdapter().hasFilteredItem();
        // We only use the default app layout when the profile of the active user has a
        // filtered item. We always show the same default app even in the inactive user profile.
        boolean currentUserAdapterHasFilteredItem;
        if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
                == UserHandle.myUserId()) {
            currentUserAdapterHasFilteredItem =
                    mMultiProfilePagerAdapter.getActiveListAdapter().hasFilteredItem();
        } else {
            currentUserAdapterHasFilteredItem =
                    mMultiProfilePagerAdapter.getInactiveListAdapter().hasFilteredItem();
        }
        return mSupportsAlwaysUseOption && currentUserAdapterHasFilteredItem;
    }

    /**
@@ -1494,9 +1575,8 @@ public class ResolverActivity extends Activity implements
                    .resolveInfoForPosition(position, true) == null) {
                return;
            }

            ListView currentAdapterView =
                    (ListView) mMultiProfilePagerAdapter.getCurrentAdapterView();
                    (ListView) mMultiProfilePagerAdapter.getActiveAdapterView();
            final int checkedPos = currentAdapterView.getCheckedItemPosition();
            final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
            if (!useLayoutWithDefault()
Loading