| /* |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.car.ui.paintbooth.widescreenime; |
| |
| import static android.view.inputmethod.EditorInfo.IME_FLAG_NO_EXTRACT_UI; |
| |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.ADD_DESC_TITLE_TO_CONTENT_AREA; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.ADD_DESC_TO_CONTENT_AREA; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.ADD_ERROR_DESC_TO_INPUT_AREA; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.REQUEST_RENDER_CONTENT_AREA; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_ITEM_ID; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_PRIMARY_IMAGE_RES_ID_LIST; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_SECONDARY_IMAGE_ID; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_SECONDARY_IMAGE_RES_ID_LIST; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_SUB_TITLE_LIST; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_TITLE_LIST; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.WIDE_SCREEN_ACTION; |
| import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.WIDE_SCREEN_EXTRACTED_TEXT_ICON_RES_ID; |
| |
| import android.content.Context; |
| import android.os.Bundle; |
| import android.text.Editable; |
| import android.text.TextWatcher; |
| import android.util.Pair; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.inputmethod.InputMethodManager; |
| import android.widget.EditText; |
| import android.widget.Toast; |
| |
| import androidx.annotation.NonNull; |
| import androidx.appcompat.app.AppCompatActivity; |
| import androidx.recyclerview.widget.RecyclerView; |
| |
| import com.android.car.ui.baselayout.Insets; |
| import com.android.car.ui.baselayout.InsetsChangedListener; |
| import com.android.car.ui.core.CarUi; |
| import com.android.car.ui.imewidescreen.CarUiImeSearchListItem; |
| import com.android.car.ui.paintbooth.R; |
| import com.android.car.ui.recyclerview.CarUiContentListItem; |
| import com.android.car.ui.recyclerview.CarUiRecyclerView; |
| import com.android.car.ui.toolbar.MenuItem; |
| import com.android.car.ui.toolbar.Toolbar; |
| import com.android.car.ui.toolbar.ToolbarController; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Activity that shows different scenarios for wide screen ime. |
| */ |
| public class WideScreenImeActivity extends AppCompatActivity implements InsetsChangedListener { |
| |
| private final List<MenuItem> mMenuItems = new ArrayList<>(); |
| private final List<Pair<CharSequence, View.OnFocusChangeListener>> mEditText = |
| new ArrayList<>(); |
| |
| private final ArrayList<String> mItemIdList = new ArrayList<>(); |
| private final ArrayList<String> mTitleList = new ArrayList<>(); |
| private final ArrayList<String> mSubTitleList = new ArrayList<>(); |
| private final ArrayList<Integer> mPrimaryImageResId = new ArrayList<>(); |
| private final ArrayList<String> mSecondaryItemId = new ArrayList<>(); |
| private final ArrayList<Integer> mSecondaryImageResId = new ArrayList<>(); |
| |
| private InputMethodManager mInputMethodManager; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.car_ui_recycler_view_activity); |
| |
| mInputMethodManager = (InputMethodManager) |
| getSystemService(Context.INPUT_METHOD_SERVICE); |
| |
| ToolbarController toolbarNonFinal = CarUi.getToolbar(this); |
| if (toolbarNonFinal == null) { |
| toolbarNonFinal = requireViewById(R.id.toolbar); |
| } |
| ToolbarController toolbar = toolbarNonFinal; |
| toolbar.setTitle(getTitle()); |
| toolbar.setState(Toolbar.State.SUBPAGE); |
| toolbar.setLogo(R.drawable.ic_launcher); |
| toolbar.registerOnBackListener( |
| () -> { |
| if (toolbar.getState() == Toolbar.State.SEARCH |
| || toolbar.getState() == Toolbar.State.EDIT) { |
| toolbar.setState(Toolbar.State.SUBPAGE); |
| return true; |
| } |
| return false; |
| }); |
| |
| CarUiContentListItem.OnClickListener mainClickListener = i -> |
| Toast.makeText(this, "Item clicked!", Toast.LENGTH_SHORT).show(); |
| |
| CarUiContentListItem.OnClickListener secondaryClickListener = i -> |
| Toast.makeText(this, "Item's secondary action clicked!", Toast.LENGTH_SHORT).show(); |
| |
| final int[] count = {1}; |
| CarUiImeSearchListItem item = new CarUiImeSearchListItem(CarUiContentListItem.Action.ICON); |
| item.setTitle("Title " + count[0]); |
| item.setBody("Sub title " + count[0]); |
| item.setIconResId(R.drawable.ic_launcher); |
| item.setSupplementalIconResId(R.drawable.ic_launcher); |
| item.setSupplementalIcon(getDrawable(R.drawable.ic_launcher), secondaryClickListener); |
| item.setOnItemClickedListener(mainClickListener); |
| |
| List<CarUiImeSearchListItem> searchItems = new ArrayList<>(); |
| |
| searchItems.add(item); |
| |
| // initial list to display in search view. |
| toolbar.setSearchItemsForWideScreen(searchItems); |
| |
| toolbar.registerOnSearchListener((query) -> { |
| count[0]++; |
| CarUiImeSearchListItem item1 = new CarUiImeSearchListItem( |
| CarUiContentListItem.Action.ICON); |
| item1.setTitle("Title " + count[0]); |
| item1.setBody("Sub title " + count[0]); |
| item1.setIconResId(R.drawable.ic_launcher); |
| item1.setSupplementalIconResId(R.drawable.ic_launcher); |
| item1.setSupplementalIcon(getDrawable(R.drawable.ic_launcher), secondaryClickListener); |
| item1.setOnItemClickedListener(mainClickListener); |
| searchItems.add(item1); |
| |
| toolbar.setSearchItemsForWideScreen(searchItems); |
| }); |
| |
| mMenuItems.add(MenuItem.builder(this) |
| .setToSearch() |
| .setOnClickListener(i -> { |
| toolbar.setState(Toolbar.State.SEARCH); |
| }) |
| .build()); |
| |
| toolbar.setMenuItems(mMenuItems); |
| |
| mEditText.add(Pair.create("Default Input Edit Text field", null)); |
| |
| mEditText.add(Pair.create("Add Desc to content area", |
| this::addDescToContentArea)); |
| |
| mEditText.add(Pair.create("Hide the content area", |
| this::hideContentArea)); |
| |
| mEditText.add(Pair.create("Hide extraction view", |
| this::hideExtractionView)); |
| |
| for (int i = 0; i < 7; i++) { |
| mItemIdList.add("itemId" + i); |
| mTitleList.add("Title " + i); |
| mSubTitleList.add("subtitle " + i); |
| mPrimaryImageResId.add(R.drawable.ic_launcher); |
| mSecondaryItemId.add("imageId" + i); |
| mSecondaryImageResId.add(R.drawable.ic_launcher); |
| } |
| |
| mEditText.add(Pair.create("Show IME list view", this::showImeListView)); |
| |
| mEditText.add(Pair.create("Add icon to extracted view", this::addIconToExtractedView)); |
| |
| mEditText.add( |
| Pair.create("Add error message to content area", this::addErrorDescToContentArea)); |
| |
| CarUiRecyclerView recyclerView = requireViewById(R.id.list); |
| recyclerView.setAdapter(mAdapter); |
| } |
| |
| private void addIconToExtractedView(View view, boolean hasFocus) { |
| if (!hasFocus) { |
| return; |
| } |
| |
| Bundle bundle = new Bundle(); |
| bundle.putInt(WIDE_SCREEN_EXTRACTED_TEXT_ICON_RES_ID, R.drawable.car_ui_icon_edit); |
| mInputMethodManager.sendAppPrivateCommand(view, WIDE_SCREEN_ACTION, bundle); |
| } |
| |
| private void addErrorDescToContentArea(View view, boolean hasFocus) { |
| if (!hasFocus) { |
| return; |
| } |
| |
| Bundle bundle = new Bundle(); |
| bundle.putString(ADD_ERROR_DESC_TO_INPUT_AREA, "Some error message"); |
| bundle.putString(ADD_DESC_TITLE_TO_CONTENT_AREA, "Title"); |
| bundle.putString(ADD_DESC_TO_CONTENT_AREA, "Description provided by the application"); |
| mInputMethodManager.sendAppPrivateCommand(view, WIDE_SCREEN_ACTION, bundle); |
| } |
| |
| private void showImeListView(View view, boolean hasFocus) { |
| if (!hasFocus) { |
| return; |
| } |
| |
| Bundle bundle = new Bundle(); |
| |
| EditText editText = (EditText) view; |
| editText.addTextChangedListener(new TextWatcher() { |
| @Override |
| public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
| |
| } |
| |
| @Override |
| public void onTextChanged(CharSequence s, int start, int before, int count) { |
| |
| } |
| |
| @Override |
| public void afterTextChanged(Editable s) { |
| mItemIdList.add("itemId " + s.toString()); |
| mTitleList.add("Title " + s.toString()); |
| mSubTitleList.add("subtitle "); |
| mPrimaryImageResId.add(R.drawable.ic_launcher); |
| mSecondaryItemId.add("imageId" + s.toString()); |
| mSecondaryImageResId.add(R.drawable.ic_launcher); |
| |
| bundle.putStringArrayList(SEARCH_RESULT_TITLE_LIST, mTitleList); |
| bundle.putStringArrayList(SEARCH_RESULT_SUB_TITLE_LIST, mSubTitleList); |
| bundle.putIntegerArrayList(SEARCH_RESULT_PRIMARY_IMAGE_RES_ID_LIST, |
| mPrimaryImageResId); |
| mInputMethodManager.sendAppPrivateCommand(view, WIDE_SCREEN_ACTION, bundle); |
| } |
| }); |
| |
| bundle.putStringArrayList(SEARCH_RESULT_ITEM_ID, mItemIdList); |
| bundle.putStringArrayList(SEARCH_RESULT_TITLE_LIST, mTitleList); |
| bundle.putStringArrayList(SEARCH_RESULT_SUB_TITLE_LIST, mSubTitleList); |
| bundle.putStringArrayList(SEARCH_RESULT_SECONDARY_IMAGE_ID, mSecondaryItemId); |
| bundle.putIntegerArrayList(SEARCH_RESULT_PRIMARY_IMAGE_RES_ID_LIST, mPrimaryImageResId); |
| bundle.putIntegerArrayList(SEARCH_RESULT_SECONDARY_IMAGE_RES_ID_LIST, mSecondaryImageResId); |
| mInputMethodManager.sendAppPrivateCommand(view, WIDE_SCREEN_ACTION, bundle); |
| } |
| |
| private void hideExtractionView(View view, boolean hasFocus) { |
| if (!hasFocus) { |
| return; |
| } |
| |
| EditText editText = (EditText) view; |
| editText.setImeOptions(IME_FLAG_NO_EXTRACT_UI); |
| |
| Bundle bundle = new Bundle(); |
| bundle.putBoolean(REQUEST_RENDER_CONTENT_AREA, false); |
| mInputMethodManager.sendAppPrivateCommand(view, WIDE_SCREEN_ACTION, bundle); |
| } |
| |
| private void addDescToContentArea(View view, boolean hasFocus) { |
| if (!hasFocus) { |
| return; |
| } |
| |
| Bundle bundle = new Bundle(); |
| bundle.putString(ADD_DESC_TITLE_TO_CONTENT_AREA, "Title"); |
| bundle.putString(ADD_DESC_TO_CONTENT_AREA, "Description provided by the application"); |
| mInputMethodManager.sendAppPrivateCommand(view, WIDE_SCREEN_ACTION, bundle); |
| } |
| |
| private void hideContentArea(View view, boolean hasFocus) { |
| if (!hasFocus) { |
| return; |
| } |
| |
| Bundle bundle = new Bundle(); |
| bundle.putBoolean(REQUEST_RENDER_CONTENT_AREA, false); |
| mInputMethodManager.sendAppPrivateCommand(view, WIDE_SCREEN_ACTION, bundle); |
| } |
| |
| |
| private static class ViewHolder extends RecyclerView.ViewHolder { |
| |
| private final EditText mEditText; |
| |
| ViewHolder(View itemView) { |
| super(itemView); |
| mEditText = itemView.requireViewById(R.id.edit_text); |
| } |
| |
| public void bind(CharSequence title, View.OnFocusChangeListener listener) { |
| mEditText.setText(title); |
| mEditText.setOnFocusChangeListener(listener); |
| } |
| } |
| |
| private final RecyclerView.Adapter<ViewHolder> mAdapter = |
| new RecyclerView.Adapter<ViewHolder>() { |
| @Override |
| public int getItemCount() { |
| return mEditText.size(); |
| } |
| |
| @Override |
| public ViewHolder onCreateViewHolder(ViewGroup parent, int position) { |
| View item = |
| LayoutInflater.from(parent.getContext()) |
| .inflate(R.layout.edit_text_list_item, |
| parent, false); |
| |
| return new ViewHolder(item); |
| } |
| |
| @Override |
| public void onBindViewHolder(@NonNull ViewHolder holder, int position) { |
| Pair<CharSequence, View.OnFocusChangeListener> pair = mEditText.get(position); |
| holder.bind(pair.first, pair.second); |
| } |
| }; |
| |
| @Override |
| public void onCarUiInsetsChanged(@NonNull Insets insets) { |
| requireViewById(R.id.list) |
| .setPadding(0, insets.getTop(), 0, insets.getBottom()); |
| requireViewById(android.R.id.content) |
| .setPadding(insets.getLeft(), 0, insets.getRight(), 0); |
| } |
| } |