android2018. 7. 12. 17:10

custom view tutorial 따라하기 1
 
 
There are generally two approaches to creating your own view

1, extend an existing view.
we will be extending an existing layout and combining existing views to form a new Android custom view.
2, create one from scratch (well, not totally from scratch since you will still be extending the View class)


테스트에 사용한 res는 아래의 경로에서 확인


RelativeLayout확장하고, init 부분에 inflate하여 가져온 rootView 뷰를 통해
하위 view에 접근한다는 것만 집고 넘어가자.

 
public class ValueSelector extends RelativeLayout{

    private int minValue = Integer.MIN_VALUE;
    private int maxValue = Integer.MAX_VALUE;

    private int REPEAT_INTERNAL_MS = 100;
    Handler mHandler=new Handler();
    public int getMinValue(){
        return minValue;

    }
    public void setMinValue(int minValue){
        this.minValue=minValue;
    }
    public int getMaxValue(){
        return maxValue;
    }
    public void setMaxValue(int maxValue){
        this.maxValue=maxValue;
    }



    public int getValue(){
        return Integer.valueOf(valueTextView.getText().toString());
    }
    public void setValue(int newValue){
        int value = newValue;
        if( value < minValue)
            value=minValue;
        else if (value > maxValue)
            value=maxValue;
        valueTextView.setText(String.valueOf(value));
    }

    View rootView;
    TextView valueTextView;
    View minusButton;
    View plusButton;

    public ValueSelector (Context context){
        super(context);
        init(context);

    }

    public ValueSelector(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    /**
     * init method will inflate the layout, get references to all of the child views, and setup the buttons
     * @param context
     */
    private void init (Context context){
        rootView = inflate(context, R.layout.value_selector, this);
        valueTextView = (TextView) rootView.findViewById(R.id.valueTextView);

        minusButton = rootView.findViewById(R.id.minusButton);
        plusButton = rootView.findViewById(R.id.plusButton);


        minusButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                decrementValue();
            }
        });
        plusButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                incrementValue();
            }
        });
        plusButton.setOnLongClickListener(new View.OnLongClickListener(){
            @Override
            public boolean onLongClick(View view) {
                mHandler.post(new AutoIncrementer());
                return false;
            }
        });
        minusButton.setOnLongClickListener(new View.OnLongClickListener(){

            @Override
            public boolean onLongClick(View view) {
                mHandler.post(new AutoDecrementer());
                return false;
            }
        });
    }

    private void decrementValue() {
        int currentVal= Integer.valueOf(valueTextView.getText().toString());
        if (currentVal > minValue )
            valueTextView.setText(String.valueOf(currentVal-1));
    }

    private void incrementValue() {

        int currentVal= Integer.valueOf(valueTextView.getText().toString());
        if( currentVal < maxValue ){
            valueTextView.setText(String.valueOf(currentVal+1));
        }
    }
    private class AutoIncrementer implements Runnable{
        @Override
        public void run() {
            if ( plusButton.isPressed() ){
                incrementValue();
                getHandler().postDelayed( new AutoIncrementer(), REPEAT_INTERNAL_MS);
            }
        }
    }
    private class AutoDecrementer implements Runnable{
        @Override
        public void run() {
            if( minusButton.isPressed() ){
                decrementValue();
                getHandler().postDelayed(new AutoDecrementer(),REPEAT_INTERNAL_MS);
            }
        }
    }
}




res/layout/value_selector.xml

You also might notice that the root node in the xml is merge. 
What does that do?  Since ValueSelector extends RelativeLayout, 
if we inflated a RelativeLayout, we would end up with a view that contains a RelativeLayout as its only child.  
By using merge, we can avoid that unnecessary RelativeLayout

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/valueSelector_margin_top"
        android:textSize="@dimen/valueSelector_text"
        android:text="0"
        android:enabled="false"
        android:background="@null"
        android:textColor="#000000"
        android:layout_centerHorizontal="true"
        android:id="@+id/valueTextView" />
    <TextView
        android:id="@+id/valueLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/valueSelector_label_text"
        android:text="@string/valueSelector_label"
        android:layout_below="@+id/valueTextView"
        android:layout_centerHorizontal="true"/>
    <ImageView
        android:src="@drawable/valueselect_minus_state"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/valueSelector_button_hMargin"
        android:layout_marginBottom="@dimen/valueSelector_button_hMargin"
        android:layout_marginRight="@dimen/valueSelector_button_insideMargin"
        android:id="@+id/minusButton"
        android:clickable="true"
        android:focusable="true"
        android:layout_centerVertical="true"
        android:layout_alignRight="@+id/valueLabel"
        />

    <ImageView
        android:src="@drawable/valueselect_plus_state"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/valueSelector_button_hMargin"
        android:layout_marginBottom="@dimen/valueSelector_button_hMargin"
        android:layout_marginLeft="@dimen/valueSelector_button_insideMargin"
        android:id="@+id/plusButton"
        android:clickable="true"
        android:focusable="true"
        android:layout_centerVertical="true"
        android:layout_alignLeft="@+id/valueLabel" />
</merge>


res/drawable/valueselect_minus_state.xml
drawable에 xml을 정의하여 button이 눌렸을 때와 아닌 경우의 image를 교차로 보여줌.

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/valueselect_pressed" />
    <item android:drawable="@drawable/valueselect_minus" />
</selector>


이제 다 만들었으니 layout에 가져다 쓰면 잘 돈다.

res/layout/activity_main.xml

<com.test.simpletest.customview.ValueSelector
android:id="@+id/valueSelector"
android:layout_width="match_parent"
android:layout_height="@dimen/valueSelector_height"
android:layout_marginLeft="@dimen/valueSelector_hMargin"
android:layout_marginRight="@dimen/valueSelector_hMargin">
</com.test.simpletest.customview.ValueSelector>






'android' 카테고리의 다른 글

custom view tutorial 따라하기 3  (0) 2018.07.16
custom view tutorial 따라하기 2  (0) 2018.07.13
Simple voice search test2  (0) 2018.07.11
Simple voice search test  (0) 2018.07.11
NDK API는 binder를 지원하지 않는다.  (0) 2018.07.03
Posted by easy16