Skip to content

Instantly share code, notes, and snippets.

@jmatsu
Forked from amyu/GeneralViewGroup.java
Last active August 29, 2015 14:19
Show Gist options
  • Save jmatsu/3445c70f2e317eb2993f to your computer and use it in GitHub Desktop.
Save jmatsu/3445c70f2e317eb2993f to your computer and use it in GitHub Desktop.
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by amyu- on 2015/04/19.
*/
public class GeneralViewGroup extends ViewGroup {
private int mParentWidth;
private int mMargin;
private OnItemClickListener mOnItemClickListener;
public GeneralViewGroup(Context context) {
this(context, null, 0);
}
public GeneralViewGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GeneralViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int childCount = getChildCount();
int height = 0;
// このrightはfor文内での制御子として動作している。
// ならforの最初に初期化因子として入れてもいい。(scopeが綺麗)
// 現在見ている行にあるViewの幅(計)かな? # => nameはinsideRowWidthとか?
int right = 0;
int viewWidth = MeasureSpec.getSize(widthMeasureSpec);
// 子要素がない => 何もしないのであればさっさと if (getChildCount() == 0) で返すべき。
// このガード節は非常に無意味。
// もしこの形で子要素がないときに拡張でできるのであればサンプルを別途用意するべき。
if (childCount > 0) {
height = getChildAt(0).getMeasuredHeight() + mMargin;
} else {
return;
}
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
// 長すぎるしMeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)は外でfinal宣言しても良いのでは。
view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
right += view.getMeasuredWidth() + mMargin;
if (viewWidth < right) {
right = view.getMeasuredWidth() + mMargin;
height += view.getMeasuredHeight() + mMargin;
}
}
// viewLengthをなぜ使わない?意味がある?
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int bottom = 0;
int right = 0;
int childCount = getChildCount();
// 大体のコメントはmeasureの方と同じ
if (childCount > 0) {
bottom = getChildAt(0).getMeasuredHeight() + mMargin;
} else {
return;
}
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
right += view.getMeasuredWidth() + mMargin;
if (mParentWidth < right) {
bottom += view.getMeasuredHeight() + mMargin;
right = view.getMeasuredWidth() + mMargin;
}
// Right, Bottomベースはイメージと合わないような気もしないでもない。
// measureと動きは似てるけど、callbackが使えない以上は仕方ないかなぁ。
// 抽出するならPoint()を使って次のr, bを取ってくるメソッドにする感じかな・・・
view.layout(
right - view.getMeasuredWidth(),
bottom - view.getMeasuredHeight(),
right,
bottom);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// parent・・・?自身の幅な気がするからmWidthOnLayoutとか。
mParentWidth = w;
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
public void addView(View child) {
child.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (mOnItemClickListener == null) {
return;
}
mOnItemClickListener.onItemClick(view);
}
});
super.addView(child);
}
// children間、それもinsideのmarginだから直感的じゃないような。
// とはいえdividerを使うわけじゃないし、spaceWidthとか・・・?
public void setMargin(int margin) {
mMargin = margin;
invalidate();
}
private void initView() {
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
// Listenerを新しく作るべきかどうか。
// touch eventをinterruptしてるわけでもdispatchしてるわけでもないから、
// 子要素を直接操作されることを考えるとあまり良くない気がする
// せっかく作るならindexとparentView(this)も欲しい
public interface OnItemClickListener {
void onItemClick(View view);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment