Я пытаюсь создать расширяемое представление списка в Android, которое использует пользовательский компонент пользовательского интерфейса в качестве дочернего, но у меня возникают проблемы с его отображением. При трассировке моего приложения с помощью отладчика я вижу, что мой пользовательский объект пользовательского интерфейса создается и данные устанавливаются, но кажется, что их тогда не добавляют в представление, даже если я возвращаю представление в конце getChildView()
.
Моя конечная цель - создать пользовательский элемент пользовательского интерфейса, ServiceSelectionCheckbox
, который я могу перетаскивать прямо с палитры макетов.
Я попытался раздувать XML для этого компонента напрямую, чтобы увидеть, была ли проблема с моим XML, приводившая к тихой ошибке, но, похоже, она раздулась нормально. Я также попытался создать вторичный более простой компонент пользовательского интерфейса со сплошным фоном, чтобы посмотреть, смогу ли я получить его, чтобы добавить правильно, что это хорошо. Это заставляет меня думать, что моя проблема связана с моим компонентом пользовательского интерфейса, ServiceSelectionCheckbox.java
, но я не могу понять, что это за проблема. Мой линтер не выдает ошибок и мой apk компилируется нормально.
Любая помощь, указывающая мне правильное направление, будет принята с благодарностью.
MainActivity.java
public class MainActivity extends AppCompatActivity {
public HashMap<String, ArrayList<Pair<String, String>>> hashMapOfServices = new HashMap<>();
public ArrayList<Pair<String, String>> aList;
public ExpandableListView list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
aList = new ArrayList<Pair<String, String>>();
aList.add(new Pair<>("Men's Haircut", "50.00"));
hashMapOfServices.put("Haircut", aList);
list = (ExpandableListView) this.findViewById(R.id.list);
list.setAdapter((ExpandableListAdapter) new ServiceExpandableListAdapter(this, this.hashMapOfServices));
}
}
Это мой пользовательский адаптер
ServiceExpandableListAdapter.java
public class ServiceExpandableListAdapter extends BaseExpandableListAdapter {
HashMap<String, ArrayList<Pair<String, String>>> hashmap;
Context mContext;
String[] selectedCategories;
TextView price;
ImageButton increment, decrement;
ConstraintLayout lowerLayout;
public static final ArrayList<String> POSSIBLECATEGORIES = new ArrayList<>(Collections.unmodifiableList(
Arrays.asList("Barber", "Braids", "Children", "Color", "Esthetician",
"Eyebrows", "Eyelashes", "Hair Extensions", "Haircut", "Make-Up",
"Massage", "Nails", "Natural Hair", "Straightening", "Style", "Tanning", "Twists", "Waxing", "Weaves")));
public ServiceExpandableListAdapter(Context context, HashMap<String, ArrayList<Pair<String, String>>> data) {
mContext = context;
hashmap = data;
selectedCategories = data.keySet().toArray(new String[data.size()]);
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater infalater = (LayoutInflater) this.mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalater.inflate(R.layout.group_heading, null);
}
TextView categoryName = (TextView) convertView.findViewById(R.id.service_category_tv);
ImageView groupHolder = (ImageView) convertView.findViewById(R.id.groupholder);
categoryName.setText(selectedCategories[groupPosition]);
return convertView;
}
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) this.mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.child_row, parent, false);
//This one works properly
// convertView = inflater.inflate(R.layout.view, parent, false);
}
//return convertView;
String category = selectedCategories[groupPosition];
ServiceSelectionCheckbox checkbox = convertView.findViewById(R.id.service_selection_checkbox);
String service = hashmap.get(category).get(childPosition).first;
checkbox.setText(service);
// Pair of format <ServiceName, Price>
Pair<String, String> testPair = new Pair<>(hashmap.get(selectedCategories[groupPosition]).get(childPosition).first, hashmap.get(selectedCategories[groupPosition]).get(childPosition).second);
if (hashmap.containsValue(testPair)) {
checkbox.setChecked(true);
} else {
checkbox.setChecked(false);
}
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public int getGroupCount() {
return this.hashmap.keySet().size();
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return hashmap.get(selectedCategories[groupPosition]).get(childPosition);
}
@Override
public Object getGroup(int groupPosition) {
return hashmap.get(selectedCategories[groupPosition]);
}
@Override
public int getChildrenCount(int groupPosition) {
return hashmap.get(selectedCategories[groupPosition]).size();
}
}
Вот файл Java для элемента пользовательского интерфейса.
ServiceSelectionCheckbox.java
public class ServiceSelectionCheckbox extends View implements View.OnClickListener {
private ConstraintLayout lowerLayout;
private ImageButton increment, decrement;
private float price;
private int quantity;
private TextView priceView, quantityView;
private CheckBox checkBox;
private boolean isQuantitySelectionVisible;
public ServiceSelectionCheckbox(Context context, AttributeSet attrs, String serviceName, String price, int quantity) {
super(context, attrs);
this.isQuantitySelectionVisible = true;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.service_selection_checkbox_layout, null);
priceView = (TextView) v.findViewById(R.id.service_selection_priceview);
checkBox = (CheckBox) v.findViewById(R.id.ssc_checkbox);
lowerLayout = (ConstraintLayout) v.findViewById(R.id.ssc_constraint_layout_quantity);
quantityView = (TextView) v.findViewById(R.id.ssc_service_quantity_countview);
increment = (ImageButton) v.findViewById(R.id.ssc_increase_service_count);
decrement = (ImageButton) v.findViewById(R.id.ssc_decrease_service_count);
}
public ServiceSelectionCheckbox(Context context) {
super(context);
this.init();
}
public ServiceSelectionCheckbox(Context context, AttributeSet attrs) {
super(context, attrs);
this.init();
}
private void init() {
this.isQuantitySelectionVisible = false;
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.service_selection_checkbox_layout, null);
priceView = (TextView) v.findViewById(R.id.service_selection_priceview);
checkBox = (CheckBox) v.findViewById(R.id.ssc_checkbox);
this.setOnClickListener(this);
lowerLayout = (ConstraintLayout) v.findViewById(R.id.ssc_constraint_layout_quantity);
quantityView = (TextView) v.findViewById(R.id.ssc_service_quantity_countview);
increment = (ImageButton) v.findViewById(R.id.ssc_increase_service_count);
decrement = (ImageButton) v.findViewById(R.id.ssc_decrease_service_count);
}
public ServiceSelectionCheckbox(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.init();
}
@Override
public void onClick(View view) {
isQuantitySelectionVisible = !isQuantitySelectionVisible;
}
@Override
public boolean performClick() {
//set lowerlayout as visible based on visible variable
if (this.isQuantitySelectionVisible) {
lowerLayout.setVisibility(View.VISIBLE);
} else {
lowerLayout.setVisibility(View.GONE);
}
return super.performClick();
}
public void setPrice(float price) {
this.price = price;
this.priceView.setText(String.valueOf(price));
}
public void setQuantity(String quantity) {
this.quantity = Integer.parseInt(quantity);
}
public void setChecked(boolean b) {
this.checkBox.setChecked(b);
}
public void setText(String serviceName) {
this.checkBox.setText(serviceName);
}
}
А вот и соответствующие файлы XML.
group_heading.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/service_category_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_weight="3"
android:fontFamily="sans-serif-light"
android:text="Categoy"
android:textSize="22sp"
android:background="@android:color/holo_orange_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/groupholder"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/groupholder"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:foregroundGravity="right"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/service_category_tv"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Это файл, который, как мне кажется, действительно доставляет мне проблемы.
child_row.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout_editor_absoluteY="81dp">
<com.example.gabriel.uitest.ServiceSelectionCheckbox
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/service_selection_checkbox"/>
</android.support.constraint.ConstraintLayout>
Отображается самостоятельно, вид создается как ожидалось.
service_selection_checkbox_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
tools:layout_editor_absoluteY="81dp">
<CheckBox
android:id="@+id/ssc_checkbox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:checked="false"
android:fontFamily="sans-serif-light"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:text="Service"
android:textAllCaps="true"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/ssc_constraint_layout_quantity"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/service_selection_priceview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:fontFamily="sans-serif-light"
android:gravity="start|center"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
android:layout_marginRight="8dp" />
<android.support.constraint.ConstraintLayout
android:id="@+id/ssc_constraint_layout_quantity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ssc_checkbox">
<ImageButton
android:id="@+id/ssc_decrease_service_count"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/ssc_service_quantity_countview"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/ssc_service_quantity_countview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:fontFamily="sans-serif-light"
android:gravity="center"
android:paddingEnd="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:text="Quantity"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/ssc_increase_service_count"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/ssc_decrease_service_count"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/ssc_increase_service_count"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/ssc_service_quantity_countview"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
Это компонент тестового представления, который я добавил для целей тестирования, упомянутых ранее, этот работает нормально.
view.xml
<?xml version="1.0" encoding="utf-8"?>
<View
android:background="@color/colorAccent"
android:layout_width="match_parent"
android:layout_height="20dp"
xmlns:android="http://schemas.android.com/apk/res/android">
</View>