From c3f818bc373e70912070ae291cef7a0384a12a4f Mon Sep 17 00:00:00 2001 From: Alexander Thiele Date: Fri, 19 Feb 2016 17:19:21 +0100 Subject: [PATCH 01/12] add EditText getter to ChipsView according to #2 --- README.md | 6 ++++++ .../src/main/java/com/doodle/android/chips/ChipsView.java | 5 +++++ .../java/com/doodle/android/chips/sample/MainActivity.java | 3 +++ 3 files changed, 14 insertions(+) diff --git a/README.md b/README.md index 2e7560c..35cab3c 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,12 @@ mChipsView.setChipsListener(new ChipsView.ChipsListener() { mChipsView.addChip(email, imgUrl, contact); ``` +**Add a non-removable chip.** + +```java +mChipsView.addChip(email, imgUrl, contact, true); +``` + **Remove a chip** ```java diff --git a/library/src/main/java/com/doodle/android/chips/ChipsView.java b/library/src/main/java/com/doodle/android/chips/ChipsView.java index e42772f..acec695 100644 --- a/library/src/main/java/com/doodle/android/chips/ChipsView.java +++ b/library/src/main/java/com/doodle/android/chips/ChipsView.java @@ -41,6 +41,7 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnectionWrapper; +import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; @@ -445,6 +446,10 @@ public void setChipsValidator(ChipValidator mChipsValidator) { this.mChipsValidator = mChipsValidator; } + public EditText getEditText() { + return mEditText; + } + private class EditTextListener implements TextWatcher { private boolean mIsPasteTextChange = false; diff --git a/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java b/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java index 0804f20..b6566ba 100644 --- a/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java +++ b/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java @@ -52,6 +52,9 @@ protected void onCreate(Bundle savedInstanceState) { mChipsView = (ChipsView) findViewById(R.id.chipsView); + // change EditText config + mChipsView.getEditText().setCursorVisible(true); + mChipsView.setChipsValidator(new ChipsView.ChipValidator() { @Override public boolean isValid(Contact contact) { From a4a17eac08c88153493d4362c38b77f3463b5752 Mon Sep 17 00:00:00 2001 From: Alexander Thiele Date: Mon, 14 Mar 2016 15:00:12 +0100 Subject: [PATCH 02/12] add chipsList getter to resolve #6 --- .../com/doodle/android/chips/ChipsView.java | 18 ++++++++++++++++++ .../doodle/android/chips/model/Contact.java | 4 ++-- .../android/chips/sample/MainActivity.java | 5 ++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/com/doodle/android/chips/ChipsView.java b/library/src/main/java/com/doodle/android/chips/ChipsView.java index acec695..ab1e2a9 100644 --- a/library/src/main/java/com/doodle/android/chips/ChipsView.java +++ b/library/src/main/java/com/doodle/android/chips/ChipsView.java @@ -24,6 +24,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; @@ -56,6 +57,7 @@ import com.squareup.picasso.Picasso; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class ChipsView extends RelativeLayout implements ChipsEditText.InputConnectionWrapperInterface, ChipsEmailDialogFragment.EmailListener { @@ -260,6 +262,11 @@ public void addChip(String displayName, Uri avatarUrl, Contact contact, boolean onChipsChanged(true); } + @NonNull + public List getChips() { + return Collections.unmodifiableList(mChipList); + } + public boolean removeChipBy(Contact contact) { for (int i = 0; i < mChipList.size(); i++) { if (mChipList.get(i).mContact != null && mChipList.get(i).mContact.equals(contact)) { @@ -694,6 +701,17 @@ public boolean equals(Object o) { } return super.equals(o); } + + @Override + public String toString() { + return "{" + + "[Contact: " + mContact + "]" + + "[Label: " + mLabel + "]" + + "[PhotoUri: " + mPhotoUri + "]" + + "[IsIndelible" + mIsIndelible + "]" + + "}" + ; + } } public interface ChipsListener { diff --git a/library/src/main/java/com/doodle/android/chips/model/Contact.java b/library/src/main/java/com/doodle/android/chips/model/Contact.java index 648acd7..989912f 100644 --- a/library/src/main/java/com/doodle/android/chips/model/Contact.java +++ b/library/src/main/java/com/doodle/android/chips/model/Contact.java @@ -73,12 +73,12 @@ public Contact(@Nullable String firstName, @Nullable String lastName, @Nullable mInitials = initialsBuilder.toString(); } - @NonNull + @Nullable public String getFirstName() { return mFirstName; } - @NonNull + @Nullable public String getLastName() { return mLastName; } diff --git a/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java b/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java index b6566ba..6536441 100644 --- a/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java +++ b/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java @@ -22,6 +22,7 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; @@ -68,7 +69,9 @@ public boolean isValid(Contact contact) { mChipsView.setChipsListener(new ChipsView.ChipsListener() { @Override public void onChipAdded(ChipsView.Chip chip) { - + for (ChipsView.Chip chipItem : mChipsView.getChips()) { + Log.d("ChipList", "chip: " + chipItem.toString()); + } } @Override From 1e944c495887bd55d3cfb7d545cc14f8e07019b9 Mon Sep 17 00:00:00 2001 From: Johannes Hoffmann Date: Fri, 1 Apr 2016 13:07:42 +0200 Subject: [PATCH 03/12] clean up --- library/build.gradle | 1 + .../com/doodle/android/chips/ChipsView.java | 7 +-- .../main/res/layout/dialog_chips_email.xml | 2 - .../android/chips/sample/MainActivity.java | 59 +++++++++++-------- sample/src/main/res/layout/activity_main.xml | 10 ++-- ...item_my.xml => item_checkable_contact.xml} | 18 ++++-- 6 files changed, 54 insertions(+), 43 deletions(-) rename sample/src/main/res/layout/{item_my.xml => item_checkable_contact.xml} (56%) diff --git a/library/build.gradle b/library/build.gradle index 7efeb5e..cfe21a3 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -24,6 +24,7 @@ dependencies { compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.rengwuxian.materialedittext:library:2.1.4' + testCompile 'junit:junit:4.12' } task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs diff --git a/library/src/main/java/com/doodle/android/chips/ChipsView.java b/library/src/main/java/com/doodle/android/chips/ChipsView.java index ab1e2a9..2bee20f 100644 --- a/library/src/main/java/com/doodle/android/chips/ChipsView.java +++ b/library/src/main/java/com/doodle/android/chips/ChipsView.java @@ -446,11 +446,8 @@ public void onDialogEmailEntered(String email, String initialText) { onEmailRecognized(new Contact(initialText, "", initialText, email, null)); } - /** - * sets the ChipsValidator. - */ - public void setChipsValidator(ChipValidator mChipsValidator) { - this.mChipsValidator = mChipsValidator; + public void setChipsValidator(ChipValidator chipsValidator) { + mChipsValidator = chipsValidator; } public EditText getEditText() { diff --git a/library/src/main/res/layout/dialog_chips_email.xml b/library/src/main/res/layout/dialog_chips_email.xml index c7acff2..3219640 100644 --- a/library/src/main/res/layout/dialog_chips_email.xml +++ b/library/src/main/res/layout/dialog_chips_email.xml @@ -64,7 +64,6 @@ android:text="@string/confirm" android:textColor="@color/blue" android:textSize="14sp" - android:textStyle="bold" /> @@ -82,7 +81,6 @@ android:text="@string/cancel" android:textColor="@color/blue" android:textSize="14sp" - android:textStyle="bold" /> diff --git a/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java b/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java index 6536441..0001b60 100644 --- a/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java +++ b/sample/src/main/java/com/doodle/android/chips/sample/MainActivity.java @@ -23,6 +23,7 @@ import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.Log; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; @@ -37,8 +38,8 @@ public class MainActivity extends AppCompatActivity { - private RecyclerView mRecyclerView; - private MyAdapter mMyAdapter; + private RecyclerView mContacts; + private ContactsAdapter mAdapter; private ChipsView mChipsView; @Override @@ -46,12 +47,12 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); - mRecyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); - mMyAdapter = new MyAdapter(); - mRecyclerView.setAdapter(mMyAdapter); + mContacts = (RecyclerView) findViewById(R.id.rv_contacts); + mContacts.setLayoutManager(new LinearLayoutManager(MainActivity.this)); + mAdapter = new ContactsAdapter(); + mContacts.setAdapter(mAdapter); - mChipsView = (ChipsView) findViewById(R.id.chipsView); + mChipsView = (ChipsView) findViewById(R.id.cv_contacts); // change EditText config mChipsView.getEditText().setCursorVisible(true); @@ -81,12 +82,12 @@ public void onChipDeleted(ChipsView.Chip chip) { @Override public void onTextChanged(CharSequence text) { - mMyAdapter.filterItems(text); + mAdapter.filterItems(text); } }); } - public class MyAdapter extends RecyclerView.Adapter { + public class ContactsAdapter extends RecyclerView.Adapter { private String[] data = new String[]{ "john@doe.com", @@ -100,18 +101,19 @@ public class MyAdapter extends RecyclerView.Adapter { private List filteredList = new ArrayList<>(); - public MyAdapter() { + public ContactsAdapter() { Collections.addAll(filteredList, data); } @Override - public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return new MyViewHolder(View.inflate(parent.getContext(), R.layout.item_my, null)); + public CheckableContactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_checkable_contact, parent, false); + return new CheckableContactViewHolder(itemView); } @Override - public void onBindViewHolder(MyViewHolder holder, int position) { - holder.textView.setText(filteredList.get(position)); + public void onBindViewHolder(CheckableContactViewHolder holder, int position) { + holder.name.setText(filteredList.get(position)); } @Override @@ -139,30 +141,35 @@ public int getItemViewType(int position) { } } - public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + public class CheckableContactViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - public final TextView textView; - public final CheckBox checkBox; + public final TextView name; + public final CheckBox selection; - public MyViewHolder(View itemView) { + public CheckableContactViewHolder(View itemView) { super(itemView); - textView = (TextView) itemView.findViewById(R.id.text_view); - checkBox = (CheckBox) itemView.findViewById(R.id.checkBox); - itemView.setOnClickListener(this); + name = (TextView) itemView.findViewById(R.id.tv_contact_name); + selection = (CheckBox) itemView.findViewById(R.id.cb_contact_selection); + selection.setOnClickListener(this); + itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + selection.performClick(); + } + }); } @Override public void onClick(View v) { - String email = textView.getText().toString(); + String email = name.getText().toString(); Uri imgUrl = Math.random() > .7d ? null : Uri.parse("https://robohash.org/" + Math.abs(email.hashCode())); Contact contact = new Contact(null, null, null, email, imgUrl); - if (checkBox.isChecked()) { - mChipsView.removeChipBy(contact); - } else { + if (selection.isChecked()) { mChipsView.addChip(email, imgUrl, contact); + } else { + mChipsView.removeChipBy(contact); } - checkBox.toggle(); } } } diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index 49f6432..f8aa248 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -14,17 +14,19 @@ android:paddingBottom="8dp" android:elevation="6dp" android:orientation="horizontal" - android:background="@color/paper"> + android:background="@color/paper" + > + android:text="To" + /> @@ -47,7 +49,7 @@ \ No newline at end of file diff --git a/sample/src/main/res/layout/item_my.xml b/sample/src/main/res/layout/item_checkable_contact.xml similarity index 56% rename from sample/src/main/res/layout/item_my.xml rename to sample/src/main/res/layout/item_checkable_contact.xml index 1256c5b..43d98b1 100644 --- a/sample/src/main/res/layout/item_my.xml +++ b/sample/src/main/res/layout/item_checkable_contact.xml @@ -1,21 +1,27 @@ + android:background="@drawable/btn_trans_base10" + > + android:layout_height="wrap_content" + /> - \ No newline at end of file + android:layout_marginLeft="8dp" + tools:text="example@domain.tld" + /> + + From 732193138fddcdb107e91211adad5dfae89aebfd Mon Sep 17 00:00:00 2001 From: Johannes Hoffmann Date: Fri, 1 Apr 2016 13:29:18 +0200 Subject: [PATCH 04/12] improve formatting --- .../com/doodle/android/chips/ChipsView.java | 72 +++++++++++-------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/library/src/main/java/com/doodle/android/chips/ChipsView.java b/library/src/main/java/com/doodle/android/chips/ChipsView.java index 2bee20f..1507da5 100644 --- a/library/src/main/java/com/doodle/android/chips/ChipsView.java +++ b/library/src/main/java/com/doodle/android/chips/ChipsView.java @@ -62,18 +62,18 @@ public class ChipsView extends RelativeLayout implements ChipsEditText.InputConnectionWrapperInterface, ChipsEmailDialogFragment.EmailListener { + // private static final String TAG = "ChipsView"; - private static final int CHIP_HEIGHT = 33; private static final int TEXT_EXTRA_TOP_MARGIN = 4; public static final int CHIP_BOTTOM_PADDING = 1; + // - // RES -------------------------------------------------- - + // private int mChipsBgRes = R.drawable.chip_background; + // - // ------------------------------------------------------ - + // private int mChipsColor; private int mChipsColorClicked; private int mChipsColorErrorClicked; @@ -91,24 +91,20 @@ public class ChipsView extends RelativeLayout implements ChipsEditText.InputConn private String mChipsDialogConfirm; private String mChipsDialogCancel; private String mChipsDialogErrorMsg; + // - // ------------------------------------------------------ - + // private float mDensity; - private ChipsListener mChipsListener; - private ChipsEditText mEditText; private ChipsVerticalLinearLayout mRootChipsLayout; - private EditTextListener mEditTextListener; - private List mChipList = new ArrayList<>(); - private Object mCurrentEditTextSpan; - private ChipValidator mChipsValidator; + // + // public ChipsView(Context context) { super(context); init(); @@ -132,7 +128,9 @@ public ChipsView(Context context, AttributeSet attrs, int defStyleAttr, int defS initAttr(context, attrs); init(); } + // + // private void initAttr(Context context, AttributeSet attrs) { TypedArray a = context.getTheme().obtainStyledAttributes( attrs, @@ -186,8 +184,6 @@ private void initAttr(Context context, AttributeSet attrs) { if (TextUtils.isEmpty(mChipsDialogErrorMsg)) { mChipsDialogErrorMsg = getResources().getString(R.string.please_enter_a_valid_email_address); } - - } finally { a.recycle(); } @@ -227,6 +223,7 @@ private void initListener() { @Override public void onClick(View v) { mEditText.requestFocus(); + unselectAllChips(); } }); @@ -236,12 +233,14 @@ public void onClick(View v) { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { - unSelectChipsExcept(null); + unselectAllChips(); } } }); } + // + // public void addChip(String displayName, String avatarUrl, Contact contact) { addChip(displayName, Uri.parse(avatarUrl), contact); } @@ -288,6 +287,20 @@ public Contact tryToRecognizeAddress() { return null; } + public void setChipsListener(ChipsListener chipsListener) { + this.mChipsListener = chipsListener; + } + + public void setChipsValidator(ChipValidator chipsValidator) { + mChipsValidator = chipsValidator; + } + + public EditText getEditText() { + return mEditText; + } + // + + // /** * rebuild all chips and place them right */ @@ -404,7 +417,7 @@ private void onChipInteraction(int position) { } private void onChipInteraction(Chip chip, boolean nameClicked) { - unSelectChipsExcept(chip); + unselectChipsExcept(chip); if (chip.isSelected()) { mChipList.remove(chip); if (mChipsListener != null) { @@ -423,7 +436,7 @@ private void onChipInteraction(Chip chip, boolean nameClicked) { } } - private void unSelectChipsExcept(Chip rootChip) { + private void unselectChipsExcept(Chip rootChip) { for (Chip chip : mChipList) { if (chip != rootChip) { chip.setSelected(false); @@ -432,28 +445,26 @@ private void unSelectChipsExcept(Chip rootChip) { onChipsChanged(false); } + private void unselectAllChips() { + unselectChipsExcept(null); + } + // + + // @Override public InputConnection getInputConnection(InputConnection target) { return new KeyInterceptingInputConnection(target); } + // - public void setChipsListener(ChipsListener chipsListener) { - this.mChipsListener = chipsListener; - } - + // @Override public void onDialogEmailEntered(String email, String initialText) { onEmailRecognized(new Contact(initialText, "", initialText, email, null)); } + // - public void setChipsValidator(ChipValidator chipsValidator) { - mChipsValidator = chipsValidator; - } - - public EditText getEditText() { - return mEditText; - } - + // private class EditTextListener implements TextWatcher { private boolean mIsPasteTextChange = false; @@ -722,4 +733,5 @@ public interface ChipsListener { public static abstract class ChipValidator { public abstract boolean isValid(Contact contact); } + // } From 4414c162424410451c98c7ccc34e00176194e9fc Mon Sep 17 00:00:00 2001 From: Johannes Hoffmann Date: Fri, 1 Apr 2016 13:54:31 +0200 Subject: [PATCH 05/12] add configurable max height attribute --- .../com/doodle/android/chips/ChipsView.java | 19 +++++++++++++++---- library/src/main/res/values/attr.xml | 1 + sample/src/main/res/layout/activity_main.xml | 5 ++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/doodle/android/chips/ChipsView.java b/library/src/main/java/com/doodle/android/chips/ChipsView.java index 1507da5..0cad2a6 100644 --- a/library/src/main/java/com/doodle/android/chips/ChipsView.java +++ b/library/src/main/java/com/doodle/android/chips/ChipsView.java @@ -64,9 +64,10 @@ public class ChipsView extends RelativeLayout implements ChipsEditText.InputConn // private static final String TAG = "ChipsView"; - private static final int CHIP_HEIGHT = 33; - private static final int TEXT_EXTRA_TOP_MARGIN = 4; - public static final int CHIP_BOTTOM_PADDING = 1; + private static final int CHIP_HEIGHT = 33; // dp + private static final int TEXT_EXTRA_TOP_MARGIN = 4; // dp + public static final int CHIP_BOTTOM_PADDING = 1; // dp + private static final int DEFAULT_MAX_HEIGHT = -1; // // @@ -74,6 +75,8 @@ public class ChipsView extends RelativeLayout implements ChipsEditText.InputConn // // + private int mMaxHeight; // px + private int mChipsColor; private int mChipsColorClicked; private int mChipsColorErrorClicked; @@ -130,13 +133,21 @@ public ChipsView(Context context, AttributeSet attrs, int defStyleAttr, int defS } // - // + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if(mMaxHeight != DEFAULT_MAX_HEIGHT) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxHeight, MeasureSpec.AT_MOST); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + private void initAttr(Context context, AttributeSet attrs) { TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.ChipsView, 0, 0); try { + mMaxHeight = a.getDimensionPixelSize(R.styleable.ChipsView_cv_max_height, DEFAULT_MAX_HEIGHT); mChipsColor = a.getColor(R.styleable.ChipsView_cv_color, ContextCompat.getColor(context, R.color.base30)); mChipsColorClicked = a.getColor(R.styleable.ChipsView_cv_color_clicked, diff --git a/library/src/main/res/values/attr.xml b/library/src/main/res/values/attr.xml index 78f2771..6e3d3dd 100644 --- a/library/src/main/res/values/attr.xml +++ b/library/src/main/res/values/attr.xml @@ -17,5 +17,6 @@ + \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index f8aa248..50365b8 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -1,6 +1,7 @@ + android:layout_height="wrap_content" + app:cv_max_height="120dp" + />