Я пытаюсь создать пользовательский компонент и поместить его в контейнер. Пользовательский компонент - это просто линейный макет с несколькими кликабельными значками. Проблема в том, что когда я показываю пользовательский вид непосредственно в основном макете, он работает. Но если я попытаюсь заменить структуру кадра своим фрагментом, пользовательский вид не отобразится. Любая идея, как я могу решить это? Спасибо!
Вот xml для пользовательского представления:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="@+id/img0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="150dp"
/>
<ImageView
android:id="@+id/img1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="2dp"
/>
<ImageView
android:id="@+id/img2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="2dp"
/>
<ImageView
android:id="@+id/img3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="2dp"
/>
<ImageView
android:id="@+id/img4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="2dp"
/>
</merge>
Для этого пользовательского представления доступны следующие атрибуты:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ColorOptionsView">
<attr name="titleText" format="string" localization="suggested" />
<attr name="valueColor" format="color" />
</declare-styleable>
<declare-styleable name="ImageSelectionView">
<attr name="filter_color" format="color" />
<attr name="img_src0" format="reference"/>
<attr name="img_src1" format="reference"/>
<attr name="img_src2" format="reference"/>
<attr name="img_src3" format="reference"/>
<attr name="img_src4" format="reference"/>
</declare-styleable>
</resources>
Это пользовательское представление отображается вмакет фрагмента:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:custom="http://schemas.android.com/tools"
android:orientation="vertical"
android:scrollbars="vertical">
<vu.co.yingcelestine.democustomcomponent.ImageSelectionView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginStart="2dp"
custom:filter_color="#ff33aa33"
custom:img_src0="@drawable/ic_happy"
custom:img_src1="@drawable/ic_good_mood"
custom:img_src2="@drawable/ic_cool"
custom:img_src3="@drawable/ic_mood_bad"
custom:img_src4="@drawable/ic_sad"
/>
</LinearLayout>
Основной макет имеет только один FrameLayout
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:custom="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<!-- <vu.co.yingcelestine.democustomcomponent.ImageSelectionView-->
<!-- custom:filter_color="#ff33aa33"-->
<!-- custom:img_src0="@drawable/ic_happy"-->
<!-- custom:img_src1="@drawable/ic_good_mood"-->
<!-- custom:img_src2="@drawable/ic_cool"-->
<!-- custom:img_src3="@drawable/ic_mood_bad"-->
<!-- custom:img_src4="@drawable/ic_sad"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:layout_gravity="center"-->
<!-- android:layout_marginStart="2dp" />-->
</LinearLayout>
Поведение пользовательского представления определяется в этом классе Java:
package vu.co.yingcelestine.democustomcomponent;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.Arrays;
import java.util.List;
public class ImageSelectionView extends LinearLayout implements View.OnClickListener {
private List<ImageView> imageViewList;
private int filterColor;
private Context context;
private AttributeSet attributeSet;
public ImageSelectionView(Context context) {
super(context);
}
@SuppressLint("ResourceAsColor")
public ImageSelectionView(Context context, AttributeSet attrs) {
super(context, attrs);
this.attributeSet = attrs;
this.context = context;
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
assert inflater != null;
inflater.inflate(R.layout.image_selection_view, this, true);
TypedArray a = context.obtainStyledAttributes(attributeSet,
R.styleable.ImageSelectionView, 0, 0);
filterColor = a.getColor(R.styleable.ImageSelectionView_filter_color,
android.R.color.holo_blue_light);
Drawable i0Src = a.getDrawable(R.styleable.ImageSelectionView_img_src0);
Drawable i1Src = a.getDrawable(R.styleable.ImageSelectionView_img_src1);
Drawable i2Src = a.getDrawable(R.styleable.ImageSelectionView_img_src2);
Drawable i3Src = a.getDrawable(R.styleable.ImageSelectionView_img_src3);
Drawable i4Src = a.getDrawable(R.styleable.ImageSelectionView_img_src4);
a.recycle();
ImageView i0 = (ImageView) getChildAt(0);
ImageView i1 = (ImageView) getChildAt(1);
ImageView i2 = (ImageView) getChildAt(2);
ImageView i3 = (ImageView) getChildAt(3);
ImageView i4 = (ImageView) getChildAt(4);
i0.setImageDrawable(i0Src);
i1.setImageDrawable(i1Src);
i2.setImageDrawable(i2Src);
i3.setImageDrawable(i3Src);
i4.setImageDrawable(i4Src);
imageViewList = Arrays.asList(
i0,
i1,
i2,
i3,
i4
);
setImagesToGray();
i0.setColorFilter(filterColor);
setImagesOnClickListener();
}
@SuppressLint("ResourceAsColor")
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
private void setImagesOnClickListener() {
for(ImageView v: imageViewList) {
v.setOnClickListener(this);
}
}
private void setImagesToGray() {
for(ImageView v: imageViewList) {
v.setColorFilter(0xffaaaaaa);
}
}
@Override
public void onClick(View v) {
if (v instanceof ImageView) {
setImagesToGray();
ImageView imageView = (ImageView) v;
imageView.setColorFilter(filterColor);
}
}
}
Позволяет пользователю выделить один из пяти значков.
В RecordsFragment
используется настраиваемое представление:
package vu.co.yingcelestine.democustomcomponent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class RecordsFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_records, container, false);
}
}
А вот основное действие:
package vu.co.yingcelestine.democustomcomponent;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, new RecordsFragment())
.commit();
}
}
Проект можно найти на github: https://github.com/yingcelestine/DemoCustomComponent