Android의 StackView에서는 할 수없는 일

소개 결론입니다만, StackView는 이름으로부터 앱 이용(사용) 이력이라고 불리는 화면과 같은 UI를 구현하는데 사용하는 것 같은 인상을 받습니다만, StackView를 사용해 실현할 수 없습니다.

이름에 따라 낭비를 접는 사람이 늘어나지 않기 위해 이번에는 Android의 StackView에 대해 요약합니다.

우선 StackView를 표시해 봅시다.


val stackView = findViewById<StackView>(R.id.my_stack_view)
stackView.adapter = object: BaseAdapter() {
    override fun getCount(): Int {
        return 10
    }

    override fun getItem(position: Int): Any? {
        return null
    }

    override fun getItemId(position: Int): Long {
        return 0
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        val v = LayoutInflater.from(this@MainActivity).inflate(R.layout.layout_stack_child, null)
        val text = v.findViewById<TextView>(R.id.stack_text)
        text.text = "Stack" + position

        return v
    }
}

실제로 사용하지 않기로 변명하면서 ...
이런 느낌으로 실장하면 실기에서는 ↓와 같은 표시를 합니다.


※ 알기 쉽게 테두리 첨부 배경도 붙이고 있습니다

아이 뷰의 표시를 그대로 한다



위에서 만든 StackView의 자식 뷰는 xml로 width/height를 match_parent로 해도 dp 지정을 해도 표시하고 있는 요소(이번의 경우는 TextView의 캐릭터 라인)의 사이즈 밖에 표시해 줍니다.

그래서 아래와 같이 LayoutParams에서 직접 변경해 보겠습니다.
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
    val v = LayoutInflater.from(this@MainActivity).inflate(R.layout.layout_stack_child, null)
    v.layoutParams = ViewGroup.LayoutParams(windowWidth,windowHeight)
    val text = v.findViewById<TextView>(R.id.stack_text)
    text.text = "Stack" + position

    return v
}



여기까지 실장해 움직여 보면, 앱 이용(사용) 이력 화면과 같은 움직임이 실장되고 있는 것을 알 수 있습니다.
그리고는 아이 뷰의 좌우 위치가 갖추어지면 완성할 것 같습니다.

StackView 사용자 정의



자식 뷰를 직접 만져도 더 이상 레이아웃을 조정할 수 없으므로 StackView를 재정의하여 사용자 정의를 진행합니다.
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
    super.onLayout(changed, left, top, right, bottom)
    val childCount = childCount
    for (i in 0 until childCount) {
        val child = getChildAt(childCount - (i + 1))
        if(child !is ImageView){
            child.layout(leftBase * (i - 1), child.top, customRight, customBottom)
        }
    }
}

조금 설명하면 leftBase는 오른쪽으로 이동하는 View의 위치를 ​​왼쪽으로 정렬하는 값입니다.
customRight/customBottom은 StackView#StackFrame의 크기가 너무 크면 앞의 View가 작게 잘리는 것을 방지하기 위해 설정합니다.
또 child가 ImageView가 아니라는 조건이 되고 있는 이유는 StackView#StackFrame이 private 클래스이기 때문입니다.

BaseAdapter의 getView로 설정한 width/height를 customRight/customBottom에 맞추어 조정하면 ↓과 같이 표시됩니다.



할 수 있다고 생각했는데 ...



마침내 앱 이용(사용) 이력 화면과 같은 UI가 실현되었을까 생각하면 여기에서 큰 함정에 빠집니다.
드래그하면 표시가 무너집니다.



낙담과 함께 조사해 보면 Stack Overflow 에 같은 일을 하려고 하는 사람이 질문하고 있었습니다.

답변을 보면 StackView는 android.widget 패키지에서만 사용할 수있는 클래스를 사용하므로 메소드를 재정의하거나 사용자 정의 StackView를 0에서 만들 수 없다는 것입니다 ...

요약



Stack Overflow를 본 사람은 알고 있다고 생각합니다만, 대답 중에 하고 싶은 것을 실현하는 라이브러리에의 링크도 있었습니다.
답변 중에는 ViewPager를 이용하고 있는 것 같은 것이 쓰여 있었으므로, 스스로 앱 이용(사용) 이력 화면을 만들고 싶은 분은 이것에 따라 ViewPager를 이용해 보세요.

좋은 웹페이지 즐겨찾기