Как я могу сделать липкие заголовки в RecyclerView? (Без внешней библиотеки)

Я хочу исправить мои заголовки в верхней части экрана, как на изображении ниже, и без использования внешних библиотек.

Введите описание изображения здесь

В моем случае я не хочу делать это в алфавитном порядке. У меня есть два разных типа просмотров (Header и normal). Я хочу только зафиксировать верхний, последний заголовок.

Solutions Collecting From Web of "Как я могу сделать липкие заголовки в RecyclerView? (Без внешней библиотеки)"

Здесь я объясню, как это сделать без внешней библиотеки. Это будет очень длинный пост, так что прикрепите себя.

Прежде всего, позвольте мне признать @ tim.paetz, чья почта вдохновила меня отправиться в путешествие по реализации моих собственных липких заголовков, используя ItemDecoration s. В моей реализации я заимствовал некоторые части своего кода.

Как вы уже могли испытать, если вы попытаетесь сделать это самостоятельно, очень сложно найти хорошее объяснение того, КАК на самом деле это делать с помощью ItemDecoration . Я имею в виду, каковы шаги? Какова его логика? Как сделать заголовок в верхней части списка? Незнание ответов на эти вопросы – это то, что заставляет других использовать внешние библиотеки, а делать это самостоятельно с помощью ItemDecoration довольно просто.

Первоначальные условия

  1. Вы должны представлять собой list элементов различного типа (не в смысле «типы Java», а в смысле «заголовок / элемент»).
  2. Ваш список должен быть отсортирован.
  3. Каждый элемент в списке должен быть определенного типа – должен быть связанный с ним элемент заголовка.
  4. Очень первым элементом в list должен быть элемент заголовка.

Здесь я предоставляю полный код для моего RecyclerView.ItemDecoration называемого HeaderItemDecoration . Затем я объясню шаги, предпринятые подробно.

 public class HeaderItemDecoration extends RecyclerView.ItemDecoration { private StickyHeaderInterface mListener; private int mStickyHeaderHeight; public HeaderItemDecoration(RecyclerView recyclerView, @NonNull StickyHeaderInterface listener) { mListener = listener; // On Sticky Header Click recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) { if (motionEvent.getY() <= mStickyHeaderHeight) { // Handle the clicks on the header here ... return true; } return false; } public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) { } public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } }); } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); View topChild = parent.getChildAt(0); if (Util.isNull(topChild)) { return; } int topChildPosition = parent.getChildAdapterPosition(topChild); if (topChildPosition == RecyclerView.NO_POSITION) { return; } View currentHeader = getHeaderViewForItem(topChildPosition, parent); fixLayoutSize(parent, currentHeader); int contactPoint = currentHeader.getBottom(); View childInContact = getChildInContact(parent, contactPoint); if (Util.isNull(childInContact)) { return; } if (mListener.isHeader(parent.getChildAdapterPosition(childInContact))) { moveHeader(c, currentHeader, childInContact); return; } drawHeader(c, currentHeader); } private View getHeaderViewForItem(int itemPosition, RecyclerView parent) { int headerPosition = mListener.getHeaderPositionForItem(itemPosition); int layoutResId = mListener.getHeaderLayout(headerPosition); View header = LayoutInflater.from(parent.getContext()).inflate(layoutResId, parent, false); mListener.bindHeaderData(header, headerPosition); return header; } private void drawHeader(Canvas c, View header) { c.save(); c.translate(0, 0); header.draw(c); c.restore(); } private void moveHeader(Canvas c, View currentHeader, View nextHeader) { c.save(); c.translate(0, nextHeader.getTop() - currentHeader.getHeight()); currentHeader.draw(c); c.restore(); } private View getChildInContact(RecyclerView parent, int contactPoint) { View childInContact = null; for (int i = 0; i < parent.getChildCount(); i++) { View child = parent.getChildAt(i); if (child.getBottom() > contactPoint) { if (child.getTop() <= contactPoint) { // This child overlaps the contactPoint childInContact = child; break; } } } return childInContact; } /** * Properly measures and layouts the top sticky header. * @param parent ViewGroup: RecyclerView in this case. */ private void fixLayoutSize(ViewGroup parent, View view) { // Specs for parent (RecyclerView) int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY); int heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED); // Specs for children (headers) int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, parent.getPaddingLeft() + parent.getPaddingRight(), view.getLayoutParams().width); int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, parent.getPaddingTop() + parent.getPaddingBottom(), view.getLayoutParams().height); view.measure(childWidthSpec, childHeightSpec); view.layout(0, 0, view.getMeasuredWidth(), mStickyHeaderHeight = view.getMeasuredHeight()); } public interface StickyHeaderInterface { /** * This method gets called by {@link HeaderItemDecoration} to fetch the position of the header item in the adapter * that is used for (represents) item at specified position. * @param itemPosition int. Adapter's position of the item for which to do the search of the position of the header item. * @return int. Position of the header item in the adapter. */ int getHeaderPositionForItem(int itemPosition); /** * This method gets called by {@link HeaderItemDecoration} to get layout resource id for the header item at specified adapter's position. * @param headerPosition int. Position of the header item in the adapter. * @return int. Layout resource id. */ int getHeaderLayout(int headerPosition); /** * This method gets called by {@link HeaderItemDecoration} to setup the header View. * @param header View. Header to set the data on. * @param headerPosition int. Position of the header item in the adapter. */ void bindHeaderData(View header, int headerPosition); /** * This method gets called by {@link HeaderItemDecoration} to verify whether the item represents a header. * @param itemPosition int. * @return true, if item at the specified adapter's position represents a header. */ boolean isHeader(int itemPosition); } } 

Бизнес-логика

Итак, как я могу заставить его придерживаться?

Вы этого не делаете. Вы не можете сделать элемент RecyclerView по вашему выбору, просто остановитесь и приклейте сверху, если только вы не являетесь гуру пользовательских макетов, и вы знаете наизусть 12 000 строк кода для RecyclerView . Поэтому, поскольку это всегда идет с дизайном пользовательского интерфейса, если вы не можете что-то сделать, подделайте его. Вы просто рисуете заголовок поверх всего, используя Canvas . Вы также должны знать, какие элементы пользователь может видеть в данный момент. Просто происходит, что ItemDecoration может предоставить вам как Canvas и информацию о видимых элементах. При этом основные шаги:

  1. В методе onDrawOver RecyclerView.ItemDecoration получают самый первый (верхний) элемент, который отображается пользователю.

      View topChild = parent.getChildAt(0); 
  2. Определите, какой заголовок представляет его.

      int topChildPosition = parent.getChildAdapterPosition(topChild); View currentHeader = getHeaderViewForItem(topChildPosition, parent); 
  3. Нарисуйте соответствующий заголовок поверх RecyclerView с помощью drawHeader() .

Я также хочу реализовать поведение, когда новый предстоящий заголовок встретит верхний: он должен выглядеть так, как если бы заголовок заголовка не выталкивал верхний текущий заголовок из представления и в конечном итоге занимает его место.

Здесь применяется тот же метод «рисования поверх всего».

  1. Определите, когда верхний «застрявший» заголовок соответствует новому предстоящему.

      View childInContact = getChildInContact(parent, contactPoint); 
  2. Получите эту точку контакта (это нижняя часть липкого заголовка, нарисованная вами, и верхняя часть предстоящего заголовка).

      int contactPoint = currentHeader.getBottom(); 
  3. Если элемент в списке нарушает эту «контактную точку», перерисуйте свой липкий заголовок, чтобы его дно было в верхней части позиции нарушения. Вы достигаете этого с помощью метода translate() Canvas . В результате начальная точка верхнего заголовка будет отсутствовать из видимой области, и она будет казаться «вытесненной предстоящим заголовком». Когда он полностью исчезнет, ​​нарисуйте новый заголовок сверху.

      if (childInContact != null) { if (mListener.isHeader(parent.getChildAdapterPosition(childInContact))) { moveHeader(c, currentHeader, childInContact); } else { drawHeader(c, currentHeader); } } 

Остальное объясняется комментариями и подробными аннотациями в куске кода, который я предоставил.

Использование прямолинейно:

 mRecyclerView.addItemDecoration(new HeaderItemDecoration((HeaderItemDecoration.StickyHeaderInterface) mAdapter)); 

Ваш mAdapter должен реализовать StickyHeaderInterface для его работы. Реализация зависит от данных, которые у вас есть.

Наконец, здесь я предоставляю gif с полупрозрачными заголовками, чтобы вы могли понять идею и посмотреть, что происходит под капотом.

Вот иллюстрация концепции «просто нарисуйся поверх всего». Вы можете видеть, что есть два элемента «header 1» – один, который мы рисуем, и остаемся сверху в застрявшей позиции, а другой – из набора данных и перемещается со всеми остальными элементами. Пользователь не увидит внутреннюю работу, потому что у вас не будет полупрозрачных заголовков.

Введите описание изображения здесь

И вот что происходит в фазе «выталкивания»:

Введите описание изображения здесь

Надеюсь, это помогло.

редактировать

Вот моя фактическая реализация метода getHeaderPositionForItem() в адаптере RecyclerView:

 @Override public int getHeaderPositionForItem(int itemPosition) { int headerPosition = 0; do { if (this.isHeader(itemPosition)) { headerPosition = itemPosition; break; } itemPosition -= 1; } while (itemPosition >= 0); return headerPosition; } 

В то время как вам не нужно использовать внешнюю библиотеку, вы всегда можете взглянуть на существующие решения с открытым исходным кодом и использовать классы, которые имеют для вас значение, чтобы придумать собственное решение, которое вам необходимо:

Заголовок-Декор

https://github.com/edubarr/header-decor

Супер тонкий

https://github.com/TonicArtos/SuperSLiM

[Устаревшие]

Recyclerview-stickyheaders

https://github.com/eowise/recyclerview-stickyheaders

Ответ уже был здесь. Если вы не хотите использовать какую-либо библиотеку, вы можете выполнить следующие действия:

  1. Сортировка списка с данными по имени
  2. Итерации через список с данными и на месте, когда первая буква текущего элемента! = Первая буква следующего элемента, вставьте «специальный» вид объекта.
  3. Внутри адаптера укажите специальный вид, когда элемент «особый».

Объяснение:

В методе onCreateViewHolder мы можем проверить viewType и в зависимости от значения (нашего «специального» вида) раздуть специальный макет.

Например:

 public static final int TITLE = 0; public static final int ITEM = 1; @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (context == null) { context = parent.getContext(); } if (viewType == TITLE) { view = LayoutInflater.from(context).inflate(R.layout.recycler_adapter_title, parent,false); return new TitleElement(view); } else if (viewType == ITEM) { view = LayoutInflater.from(context).inflate(R.layout.recycler_adapter_item, parent,false); return new ItemElement(view); } return null; } 

Где class ItemElement и class TitleElement могут выглядеть как обычный ViewHolder :

 public class ItemElement extends RecyclerView.ViewHolder { //TextView text; public ItemElement(View view) { super(view); //text = (TextView) view.findViewById(R.id.text); } 

Поэтому идея всего этого интересна. Но мне интересно, если это эффективно, потому что нам нужно отсортировать список данных. И я думаю, что это ускорит скорость. Если есть какие-то мысли об этом, напишите мне 🙂

А также открытый вопрос: как удержать «специальный» макет сверху, а предметы перерабатываются. Возможно, объединить все это с CoordinatorLayout .

Вы можете проверить и выполнить реализацию класса StickyHeaderHelper в моем проекте FlexibleAdapter и адаптировать его к вашему прецеденту.

Но я предлагаю использовать библиотеку, поскольку она упрощает и реорганизует способ, которым вы обычно реализуете адаптеры для RecyclerView: не изобретайте колесо.

Я бы также сказал: не используйте Decorators или устаревшие библиотеки, а также не используйте библиотеки, которые занимаются всего лишь 1 или 3 вещами, вам придется объединить реализации других библиотек самостоятельно.

Самый простой способ – просто создать отделку предметов для вашего RecyclerView.

 import android.graphics.Canvas; import android.graphics.Rect; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class RecyclerSectionItemDecoration extends RecyclerView.ItemDecoration { private final int headerOffset; private final boolean sticky; private final SectionCallback sectionCallback; private View headerView; private TextView header; public RecyclerSectionItemDecoration(int headerHeight, boolean sticky, @NonNull SectionCallback sectionCallback) { headerOffset = headerHeight; this.sticky = sticky; this.sectionCallback = sectionCallback; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int pos = parent.getChildAdapterPosition(view); if (sectionCallback.isSection(pos)) { outRect.top = headerOffset; } } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); if (headerView == null) { headerView = inflateHeaderView(parent); header = (TextView) headerView.findViewById(R.id.list_item_section_text); fixLayoutSize(headerView, parent); } CharSequence previousHeader = ""; for (int i = 0; i < parent.getChildCount(); i++) { View child = parent.getChildAt(i); final int position = parent.getChildAdapterPosition(child); CharSequence title = sectionCallback.getSectionHeader(position); header.setText(title); if (!previousHeader.equals(title) || sectionCallback.isSection(position)) { drawHeader(c, child, headerView); previousHeader = title; } } } private void drawHeader(Canvas c, View child, View headerView) { c.save(); if (sticky) { c.translate(0, Math.max(0, child.getTop() - headerView.getHeight())); } else { c.translate(0, child.getTop() - headerView.getHeight()); } headerView.draw(c); c.restore(); } private View inflateHeaderView(RecyclerView parent) { return LayoutInflater.from(parent.getContext()) .inflate(R.layout.recycler_section_header, parent, false); } /** * Measures the header view to make sure its size is greater than 0 and will be drawn * https://yoda.entelect.co.za/view/9627/how-to-android-recyclerview-item-decorations */ private void fixLayoutSize(View view, ViewGroup parent) { int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY); int heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED); int childWidth = ViewGroup.getChildMeasureSpec(widthSpec, parent.getPaddingLeft() + parent.getPaddingRight(), view.getLayoutParams().width); int childHeight = ViewGroup.getChildMeasureSpec(heightSpec, parent.getPaddingTop() + parent.getPaddingBottom(), view.getLayoutParams().height); view.measure(childWidth, childHeight); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); } public interface SectionCallback { boolean isSection(int position); CharSequence getSectionHeader(int position); } 

}

XML для вашего заголовка в recycler_section_header.xml:

 <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_item_section_text" android:layout_width="match_parent" android:layout_height="@dimen/recycler_section_header_height" android:background="@android:color/black" android:paddingLeft="10dp" android:paddingRight="10dp" android:textColor="@android:color/white" android:textSize="14sp" /> 

И, наконец, добавить украшение предметов в ваш RecyclerView:

 RecyclerSectionItemDecoration sectionItemDecoration = new RecyclerSectionItemDecoration(getResources().getDimensionPixelSize(R.dimen.recycler_section_header_height), true, // true for sticky, false for not new RecyclerSectionItemDecoration.SectionCallback() { @Override public boolean isSection(int position) { return position == 0 || people.get(position) .getLastName() .charAt(0) != people.get(position - 1) .getLastName() .charAt(0); } @Override public CharSequence getSectionHeader(int position) { return people.get(position) .getLastName() .subSequence(0, 1); } }); recyclerView.addItemDecoration(sectionItemDecoration); 

С помощью этого украшения предметов вы можете сделать заголовок прикрепленным / липким или нет с помощью только логического значения при создании украшения предмета.

Вы можете найти полный рабочий пример github: https://github.com/paetztm/recycler_view_headers

| * | После одного полного дня борьбы, который я разработал ниже Сессионного адаптера или класса менеджера
Который прост в использовании, просто скопируйте вставку и укажите свой список и значения.

Это поможет всем, кого я не хочу бороться, как я.


| * | Укажите имена заголовков в SsnHdrAryVar:

 String SsnHdrAryVar[] = {"NamHdr1", "NamHdr2", "NamHdr3"}; 

| * | Укажите количество подэлементов, отображаемых в каждом сеансе в SsnItmCwtAryVar, соответственно:

 int SsnItmCwtAryVar[] = {2, 3, 5}; 

| * | Укажите высоту заголовка сеанса в SsnHdrHytVar:

  int SsnHdrHytVar = 100; 

| * | Укажите цвет фона заголовка и цвет текста:

  int SsnHdrBgdClr = Color.GREEN; int SsnHdrTxtClr = Color.MAGENTA; 

| * | Укажите true, если вам нужен личный заголовок сеанса:

  boolean SsnStkVab = true; 

| * | Полный класс класса класса активности (исключая List Adopter и Get ArrayList)

 public class NamLysSrnCls extends Activity { ArrayList<ItmLysCls> ItmAryLysVar = new ArrayList<>(); // CodTdo :=> Specify all your requirement here : String SsnHdrAryVar[] = {"NamHdr1", "NamHdr2", "NamHdr3"}; int SsnItmCwtAryVar[] = {2, 3, 5}; int LysItmHytVal = 200; int SsnHdrHytVar = 100; int SsnHdrBgdClr = Color.GREEN; int SsnHdrTxtClr = Color.MAGENTA; boolean SsnStkVab = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); RecyclerView NamLysLyoVav = new RecyclerView(this); NamLysAdrCls NamLysAdrVar = new NamLysAdrCls(GetItmAryLysFnc()); NamLysLyoVav.setAdapter(NamLysAdrVar); NamLysLyoVav.setLayoutManager(new LinearLayoutManager(this)); NamLysLyoVav.addItemDecoration(new LysSsnMgrCls()); // CodTdo :=> If you need Horizontal Lines : NamLysLyoVav.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); setContentView(NamLysLyoVav); } // TskTdo :=> Add Below List Seesion Manager or Adoptor Class to ur List activity class class LysSsnMgrCls extends RecyclerView.ItemDecoration { private RelativeLayout SsnHdrVav; private TextView SsnHdrTxtVav; private int SsnHdrRefIdxAryVar[]; public LysSsnMgrCls() { SsnHdrRefIdxAryVar = new int[ItmAryLysVar.size()]; int TmpSsnHdrIdxVar = 0; int TmpItmCwtAdnVar = SsnItmCwtAryVar[0]; for(int IdxVat = 1; IdxVat < ItmAryLysVar.size(); IdxVat++) { if(IdxVat < TmpItmCwtAdnVar) SsnHdrRefIdxAryVar[IdxVat] = TmpSsnHdrIdxVar; else { TmpSsnHdrIdxVar++; TmpItmCwtAdnVar += SsnItmCwtAryVar[TmpSsnHdrIdxVar]; SsnHdrRefIdxAryVar[IdxVat] = TmpSsnHdrIdxVar; } Log.d("TAG", "onCreate: " + SsnHdrRefIdxAryVar[IdxVat]); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int LysItmIdxVal = parent.getChildAdapterPosition(view); if (ChkSsnHasHdrFnc(LysItmIdxVal)) { outRect.top = SsnHdrHytVar; } } @Override public void onDrawOver(Canvas SsnCanvasPsgVal, RecyclerView SupLysLyoPsgVav, RecyclerView.State LysSttPsgVal) { super.onDrawOver(SsnCanvasPsgVal, SupLysLyoPsgVav, LysSttPsgVal); if (SsnHdrVav == null) { // TskTdo :=> Design Session Header : SsnHdrVav = new RelativeLayout(NamLysSrnCls.this); SsnHdrVav.setBackgroundColor(SsnHdrBgdClr); SsnHdrVav.setLayoutParams(new LinearLayoutCompat.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); SsnHdrTxtVav = new TextView(NamLysSrnCls.this); SsnHdrTxtVav.setPadding(20,10,20,10); SsnHdrTxtVav.setLayoutParams(new LinearLayoutCompat.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); SsnHdrTxtVav.setTextColor(SsnHdrTxtClr); SsnHdrTxtVav.setTextSize(20); SsnHdrTxtVav.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); SsnHdrVav.addView(SsnHdrTxtVav); LyoSyzFixFnc(SsnHdrVav, SupLysLyoPsgVav); } for (int i = 0; i < SupLysLyoPsgVav.getChildCount(); i++) { View DspSubVyuVav = SupLysLyoPsgVav.getChildAt(i); final int LysItmIdxVal = SupLysLyoPsgVav.getChildAdapterPosition(DspSubVyuVav); if (ChkSsnHasHdrFnc(LysItmIdxVal)) { String title = GetSsnHdrTxtFnc(LysItmIdxVal); SsnHdrTxtVav.setText(title); DevSsnHdrFnc(SsnCanvasPsgVal, DspSubVyuVav, SsnHdrVav); } } } boolean ChkSsnHasHdrFnc(int LysItmIdxPsgVal) { return LysItmIdxPsgVal == 0 ? true : SsnHdrRefIdxAryVar[LysItmIdxPsgVal] != SsnHdrRefIdxAryVar[LysItmIdxPsgVal - 1]; } String GetSsnHdrTxtFnc(int LysItmIdxPsgVal) { return SsnHdrAryVar[SsnHdrRefIdxAryVar[LysItmIdxPsgVal]]; } private void DevSsnHdrFnc(Canvas HdrCanvasPsgVal, View DspSubItmPsgVav, View SsnHdrPsgVav) { HdrCanvasPsgVal.save(); if (SsnStkVab) HdrCanvasPsgVal.translate(0, Math.max(0, DspSubItmPsgVav.getTop() - SsnHdrPsgVav.getHeight())); else HdrCanvasPsgVal.translate(0, DspSubItmPsgVav.getTop() - SsnHdrPsgVav.getHeight()); SsnHdrPsgVav.draw(HdrCanvasPsgVal); HdrCanvasPsgVal.restore(); } private void LyoSyzFixFnc(View SsnHdrVyuPsgVal, ViewGroup SupLysLyoPsgVav) { int LysLyoWytVal = View.MeasureSpec.makeMeasureSpec(SupLysLyoPsgVav.getWidth(), View.MeasureSpec.EXACTLY); int LysLyoHytVal = View.MeasureSpec.makeMeasureSpec(SupLysLyoPsgVav.getHeight(), View.MeasureSpec.UNSPECIFIED); int SsnHdrWytVal = ViewGroup.getChildMeasureSpec(LysLyoWytVal, SupLysLyoPsgVav.getPaddingLeft() + SupLysLyoPsgVav.getPaddingRight(), SsnHdrVyuPsgVal.getLayoutParams().width); int SsnHdrHytVal = ViewGroup.getChildMeasureSpec(LysLyoHytVal, SupLysLyoPsgVav.getPaddingTop() + SupLysLyoPsgVav.getPaddingBottom(), SsnHdrVyuPsgVal.getLayoutParams().height); SsnHdrVyuPsgVal.measure(SsnHdrWytVal, SsnHdrHytVal); SsnHdrVyuPsgVal.layout(0, 0, SsnHdrVyuPsgVal.getMeasuredWidth(), SsnHdrVyuPsgVal.getMeasuredHeight()); } } }